gpt4 book ai didi

c++ - 这是复制值两次吗?

转载 作者:可可西里 更新时间:2023-11-01 10:55:46 26 4
gpt4 key购买 nike

假设我有这样一个类:

class Foo
{
public:
QString a;
void setA(QString val);
}

并像这样实现 setA():

void Foo::setA(QString val)
{
this->a = val;
}

并像这样使用它:

Foo f;
QString v = "foo";
f.setA(v);

我是否在堆栈上复制了两次 v 结构?一个用于传递参数,另一个用于函数内的赋值,对吗?通过使用 void setA(QString &val); 将避免复制对象两次,因为在第一个中我只是复制一个引用(指针)而不是整个对象,所以唯一的拷贝对象在赋值中:

  this->a = val;

最佳答案

Am I copying the v struct twice on stack? one for pass in the argument and other in the assignment within the function, is this right?

没错。您正在按值传递,因此必须构造一个新对象(在您的情况下,通过复制构造函数)。

现在,在 QString(以及 Qt 中的许多其他值类型)的特殊情况下,该操作非常便宜,因为 QString 是 implicitly shared (读:引用计数,写时复制)。对于其他数据类型,操作可能会很昂贵。

by rather using void setA(QString &val)

或者实际上使用 setA(const QString &val),因为您没有修改 val 引用的对象。通过使用 const 引用,您还允许使用临时对象:

void setA(QString &val);
setA(QString("foo")); // does not compile!

void setA(const QString &val);
setA(QString("foo")); // works

so the only copy of the object is in the assignment

既然你的类无论如何都会存储一个拷贝,那么一个常见的模式(参见 Modern Effective C++ 的一个大讨论)就是坚持按值传递,并使用参数的移动赋值:

void setA(QString val) {
this->a = std::move(val);
}

在这种情况下,您可以保存一个拷贝,以防使用临时/右值调用 setA(val 将被移动构造,然后您将再次移动,导致 2 个移动而不是 1 个拷贝 + const 引用方法的 1 个移动)。如果使用左值调用 setA,您需要支付 1 个拷贝 + 1 个移动(而不是 1 个常量引用方法的拷贝)。

关于c++ - 这是复制值两次吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35089090/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com