哪种功能结构更好?

发布于 2024-12-11 23:13:38 字数 734 浏览 0 评论 0原文

看下面的代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晌融 2024-12-18 23:13:38

在这种情况下,编译器是否支持 NRVO?

定义“编译器支持”?

f1 的作用是完全破坏编译器优化MyClass 副本的能力。让我们详细看看f1

MyClass &&o=MyClass();

这会创建一个临时变量,而不是堆栈变量。然后,将该临时变量绑定到一个名为 o 的右值引用,这将临时变量的生命周期延长到函数末尾。

return std::move(o); //or return static_cast<MyClass &&>(o);

这将返回临时堆栈绑定右值引用的右值引用。由于您返回的是一个值,而不是一个引用,因此编译器必须从中创建一个临时值。

将临时文件复制/移动到 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最坏的情况< /em> 等于 f1。而且很可能会更好。

请停止试图超越编译器。让复制省略发挥作用即可。

are there any compiler support of NRVO in this case?

Define "compiler support"?

What f1 does is completely destroy the compiler's ability to optimize the copy of MyClass. Let's look at f1 in detail

MyClass &&o=MyClass();

This 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.

return std::move(o); //or return static_cast<MyClass &&>(o);

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:

create temporary
copy/move from temporary to return value
elide copy/move from return value to `a`.

f2 does:

create stack variable
elide copy/move from stack variable to `b`.

If NVRO doesn't exist, you have:

create stack variable
copy/move from stack variable to return value
elide copy/move from stack variable to `b`.

So, f2 is at worst equal to f1. And more than likely, better.

Please stop trying to out-think the compiler. Just let copy elision do its job.

溺ぐ爱和你が 2024-12-18 23:13:38

这就是当前编译器(MSVC10 / gcc trunk)的工作原理:
假设 MyClass 是可移动的

f1 : move   
f2 :   
worst case : move 
best case : NRVO 

假设 MyClass 是不可移动的:

f1 : copy    
f2 :    
worst case : copy    
best case : NRVO 

因此,即使编译器变得更好并开始对 f1 等函数执行 NRVO,当 f2 经典 C++03 函数已经是最佳函数时,为什么还要使代码复杂化呢?

This is how current compilers (MSVC10 / gcc trunk) works :
Assuming MyClass is moveable

f1 : move   
f2 :   
worst case : move 
best case : NRVO 

Assuming MyClass is not moveable :

f1 : copy    
f2 :    
worst case : copy    
best case : NRVO 

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 ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文