首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么“部分RVO”没有执行?

为什么“部分RVO”没有执行?
EN

Stack Overflow用户
提问于 2019-05-29 09:44:24
回答 2查看 251关注 0票数 6

请看一下这个愚蠢的函数,它只会说明问题和简化真正的代码:

代码语言:javascript
复制
struct A;

A create(bool first){
        A f(21), s(42);
        if(first)
           return f;
        else
           return s;
}

我理解,因为不清楚在编译期间将返回哪个对象,所以不能总是执行返回值优化(RVO)。

但是,在50%的情况下(假设true/false由于缺乏进一步的信息而统一分布)可能会执行RVO :只需决定应该对哪种情况执行RVO (first==truefirst==false),并将其应用于此参数-值,并接受在另一种情况下必须调用复制构造函数。

然而,对于我可以使用的所有编译器(参见使用gcc嘎吱声MSVC) --在这两种情况下(即first==truefirst==false),使用的都是复制构造函数,而不是省略。

是否存在使上述情况下的“部分RVO”无效的东西,还是所有编译器都不可能错过优化的情况?

完整程序:

代码语言:javascript
复制
#include <iostream>

struct A{
    int val;
    A(int val_):val(val_){}
    A(const A&o):val(o.val){
        std::cout<<"copying: "<<val<<"\n";
    }
};

A create(bool first){
        A f(21), s(42);
        if(first)
           return f;
        else
           return s;
}

int main(){
    std::cout<<"With true: ";
    create(true);
    std::cout<<"With false: ";
    create(false);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-29 10:17:23

让我们考虑一下如果对f执行RVO会发生什么,这意味着它是直接在返回值中构造的。如果first==truef被返回,那么就不需要拷贝了。但是如果first==false然后返回s,那么程序将在f析构函数运行之前将构造s复制到f的顶部。然后,f的析构函数将运行,现在返回的值是一个已经销毁的无效对象!

如果RVO是为s完成的,则同样的参数也适用,但现在问题发生在first==true时。

无论你选择哪一种,你都会避免在50%的情况下复制,而在其他50%的情况下,你会得到不明确的行为!这不是一个理想的优化!

为了完成这项工作,必须改变局部变量的销毁顺序,以便在将f复制到该内存位置之前销毁s (反之亦然),这是一个非常危险的问题。破坏的顺序是C++的一个基本属性,不应该被篡改,否则你会破坏RAII,谁知道还有多少其他的假设。

票数 11
EN

Stack Overflow用户

发布于 2019-05-29 11:26:28

我对此的看法是,除了饶有兴趣地阅读Jonathan的答案之外,我们始终可以为返回的对象定义一个move构造函数。如果RVO由于任何原因无法应用,并且在我看来是一个很好的解决方案,那么这将比复制构造函数更受青睐。

std::vector这样的东西定义了这样的构造函数,所以您可以免费获得它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56357604

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档