哪种功能结构更好?
看下面的代码:
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 的编译器?毕竟这似乎是未来更好的形式。
Look at the following code:
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();
}
Function f2
is the normal form of returning an object. NRVO may apply and the additional copy constructor call could be avoid. f1
is the new form that uses rvalue reference. For systems that do not support NRVO but support rvalue reference, the move constructor is called rather than copy constructor, which would be considered better in most of the cases.
The problem of f1
is that: are there any compilers that support of NRVO in this case? It seems to be the better form in the future after all.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
定义“编译器支持”?
f1
的作用是完全破坏编译器优化MyClass
副本的能力。让我们详细看看f1
这会创建一个临时变量,而不是堆栈变量。然后,将该临时变量绑定到一个名为
o
的右值引用,这将临时变量的生命周期延长到函数末尾。这将返回临时堆栈绑定右值引用的右值引用。由于您返回的是一个值,而不是一个引用,因此编译器必须从中创建一个临时值。
将临时文件复制/移动到
a
中的操作将被省略。但您仍然创建了两个临时值(原始值和返回值)。因此,
f1
执行以下操作:f2
执行以下操作:如果 NVRO 不存在,则:
因此,
f2
是最坏的情况< /em> 等于f1
。而且很可能会更好。请停止试图超越编译器。让复制省略发挥作用即可。
Define "compiler support"?
What
f1
does is completely destroy the compiler's ability to optimize the copy ofMyClass
. Let's look atf1
in detailThis creates a temporary, not a stack variable. Then that temporary is bound to an r-value reference called
o
, which extends the lifetime of the temporary to the end of the function.This returns an r-value reference of a stack-bound r-value reference to a temporary. And since you're returning a value, not a reference, the compiler has to create a temporary from it.
The copy/move of the temporary into
a
will be elided. But you still created two temporaries (the original and the return value).So
f1
does the following:f2
does:If NVRO doesn't exist, you have:
So,
f2
is at worst equal tof1
. And more than likely, better.Please stop trying to out-think the compiler. Just let copy elision do its job.
这就是当前编译器(MSVC10 / gcc trunk)的工作原理:
假设 MyClass 是可移动的
假设 MyClass 是不可移动的:
因此,即使编译器变得更好并开始对 f1 等函数执行 NRVO,当 f2 经典 C++03 函数已经是最佳函数时,为什么还要使代码复杂化呢?
This is how current compilers (MSVC10 / gcc trunk) works :
Assuming MyClass is moveable
Assuming MyClass is not moveable :
So even if compilers get better and start doing NRVO for functions like f1, why bother complicate the code when f2 classical C++03 functions are already optimal ?