在C++中,初始化类似
MyClass(myBigObject s):
s_(s)
{
...
}
好像
s
在函数入口(“按值传递”)被复制一次,并在分配给s_
时被复制一次。编译器是否足够聪明,可以删除第一个副本?
最佳答案
临时复制到s
的文件可以省略
如果传递临时对象,则优化的编译器可能会省略第一个副本:
MyClass x{ myBigObject() };
由于临时myBigObject将直接构造到构造函数参数
s
中,因此可能仅调用一次复制构造函数。请注意,这可以更改程序的可观察行为。
#include <iostream>
struct myBigObject
{
size_t x;
myBigObject() : x() {}
myBigObject(myBigObject && other)
{
std::cout << "Move myBigObject" << std::endl;
}
myBigObject(const myBigObject &other)
{
std::cout << "Copy myBigObject" << std::endl;
x = 12;
}
};
struct MyClass
{
MyClass(myBigObject s)
: s_(s)
{
std::cout << "x of s : " << s.x << std::endl;
std::cout << "x of s_ : " << s_.x << std::endl;
}
myBigObject s_;
};
int main()
{
std::cout << "A:" << std::endl;
MyClass x{ myBigObject() };
std::cout << "B:" << std::endl;
myBigObject y;
MyClass z{ y };
}
打印(https://ideone.com/hMEv1W + MSVS2013,Toolsetv120)
A:
Copy myBigObject
x of s : 0
x of s_ : 12
B:
Copy myBigObject
Copy myBigObject
x of s : 12
x of s_ : 12
无法复制到
s_
中的第二个副本由于
s_
和s
需要是不同的对象,因此不能省略复制到s_
中的操作。如果您只想在类(class)中获得一份
myBigObject
,可以申请:MyClass(myBigObject const & s)
: s_(s)
{
}
MyClass(myBigObject && s)
: s_(std::forward<myBigObject>(s))
{
}
这样,对于临时对象,您将看不到任何副本,对于非临时对象,您将仅看到一个副本。
更改后的代码将打印:
A:
Move myBigObject
B:
Copy myBigObject