C++ Copy elision

关于编译器优化
参考: 编译器优化之Copy elision、URVO、NRVO
要点:
1、返回值优化RVO(Return Value Optimization,RVO),即避免返回过程触发复制 / 移动构造函数。根据返回的值是否是匿名对象,可以分为两类:

具名返回值优化 NRVO (Named Return Value Optimization,NRVO)
匿名返回值优化 URVO(Unknown Return Value Optimization,URVO )

2、C++17以前,只有对象的移动构造函数是有效的时,RVO才可以正常使用,而在C++17以后,会强制开启URVO优化(NRVO不会强制开启),此时不再对移动构造函数有依赖(移动构造函数被URVO优化了)。

例如:

class Foo { 
    public:
        Foo() { std::cout<<"default"<<std::endl; }

        Foo(const Foo& rhs) { std::cout<<"ctor"<<std::endl; }
        // Foo(Foo&& rhs) { std::cout<<"mtor"<<std::endl; }
        // Foo(const Foo& rhs) = delete;
        Foo(Foo&& rhs) = delete;  
    };

    Foo return_urvo_value() { 
      return Foo{};    // 若没开启URVO优化,则调用两次移动构造函数
    }

    Foo return_nrvo_value() { 
      Foo local_obj;
      return local_obj; // 若没开启NRVO优化,也同样调用两次移动构造函数 
    }

int main() {
    auto x = return_urvo_value();
    std::cout<<"---------------------------------------"<<std::endl;
    auto y = return_nrvo_value();  
    return 0;
}

在c++11中,当移动构造函数=delete时,不论是否开启RVO,都无法编译通过(由于return_nrvo_value()和return_urvo_value()都依赖移动构造函数).报错:

/home/CppPearlPick/src/mySTL/src/test/test_copy_elision.cpp:15:18: error: use of deleted function ‘Foo::Foo(Foo&&)’
   15 |       return Foo{};    // 若没开启URVO优化,则调用两次移动构造函数

而当c++17时, 由于URVO强制执行,返回值不再依赖移动构造函数了,因此移动构造函数是否=delete, 都可以编译通过,其实只要移动构造和拷贝构造有任意一个是可以访问的即可。有下面几种情况:

(1)、关闭RVO优化,且移动构造函数=delete
输出为:
在这里插入图片描述
对于 auto y = return_nrvo_value(); ,由于URVO强制启用,因此return时匿名对象向y的移动被优化为直接在y空间上对local_obj进行拷贝。

(2)、关闭RVO优化,移动构造函数开启
输出为:
在这里插入图片描述
对于 auto y = return_nrvo_value(); ,由于URVO强制启用,因此return时匿名对象向y的移动被优化为直接在y空间上对local_obj进行移动。

(3)、开启RVO优化,且移动构造函数=delete

在这里插入图片描述
(4)、开启RVO优化,移动构造函数开启
在这里插入图片描述
可以看出,不论是否开启RVO优化,都会强制执行URVO,而NRVO则不会。

总结:C++17以下版本编译器RVO优化是否开启与移动构造函数是否delete,是否关闭RVO优化编译选项有关。
C++17及以上URVO是强制开启的,NRVO能否启用取决于是否开启了RVO优化的编译选项以及移动构造和拷贝构造是否至少有一个可访问。因此C++17及其以上相比于旧版本显然有着更好的编译优化能力。

附:关闭RVO优化,CMakeLists文件内容在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值