看下面的代码:
class MyClass{
public:
MyClass(){}
MyClass(MyClass &&){}
MyClass(const MyClass &){}
};
MyClass f1(){
MyClass &&o=MyClass();
/*...*/
return std::move(o);//or return static_cast<MyClass &&>(o);
}
MyClass f2(){
MyClass o=MyClass();
/*...*/
return o;
}
int main(int, char **){
auto a=f1();
auto b=f2();
}
函数 f2
是返回对象的正常形式。 NRVO可能适用,并且可以避免额外的复制构造函数调用。 f1
是使用右值引用的新形式。对于不支持 NRVO 但支持右值引用的系统,调用移动构造函数而不是复制构造函数,这在大多数情况下会被认为更好。
f1
的问题在于:在这种情况下是否有支持 NRVO 的编译器?这似乎是 future 更好的形式。
最佳答案
are there any compiler support of NRVO in this case?
定义“编译器支持”?
f1
所做的是完全破坏编译器优化MyClass
拷贝的能力。让我们详细看看f1
MyClass &&o=MyClass();
这会创建一个临时,而不是堆栈变量。然后将该临时对象绑定(bind)到名为 o
的右值引用,这将临时对象的生命周期延长到函数结束。
return std::move(o); //or return static_cast<MyClass &&>(o);
这将返回一个堆栈绑定(bind)右值引用的右值引用到一个临时值。由于您返回的是一个值,而不是一个引用,因此编译器必须从中创建一个临时值。
将临时文件复制/移动到 a
中将被省略。但是您仍然创建了两个临时值(原始值和返回值)。
因此 f1
执行以下操作:
create temporary
copy/move from temporary to return value
elide copy/move from return value to `a`.
f2
做:
create stack variable
elide copy/move from stack variable to `b`.
如果 NVRO 不存在,你有:
create stack variable
copy/move from stack variable to return value
elide copy/move from stack variable to `b`.
所以,f2
在最坏的情况下等于f1
。更有可能,更好。
请停止试图超越编译器。让复制省略完成它的工作。
关于c++ - 哪个功能结构更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7898395/