• C++编译器的RVO和NRVO


    1、说明

    我一直记得返回对象的函数在调用时会有拷贝构造动作,但是最近实际测试却和记忆有些偏差,经查询是编译的问题

    RVO: return value optimization

    NRVO: named return value optimization

    这两个是编译器的一种函数返回值优化策略

    先说结果,VS在debug模式下默认 RVO,release模式下默认 NRVO;而g++在debug和release下都默认NRVO

    2、示例

    先看一组代码

    class Test
    {
    public:
        explicit Test(int num)
            : num(num)
        {
            cout << "constructor " << num << endl;
        }
    
        Test(const Test &test)
        {
            cout << "copy constructor " << test.num << endl;
            num = test.num;
        }
    
        ~Test()
        {
            cout << "destructor " << num << endl;
        }
    
        void print() const
        {
            cout << "print " << num << endl;
        }
    private:
        int num{};
    };
    
    Test getTest(int num)
    {
        Test test(num);
        return test;
    }
    
    int main()
    {
        Test test2 = getTest(12);
        test2.print();
        return 0;
    }
    

    函数 getTest() 返回一个对象,main() 函数中调用并复制给变量理应有一个拷贝构造的动作,但是实际上返回值为

    constructor 12
    print 12
    destructor 12
    

    打印变量地址也发现,getTest() 函数内的变量 test 和 main() 函数中的变量 test 的地址居然是一样的。是我记错了吗?其实不是,根据C++语法,确实应该有拷贝构造的动作,这里的结果是编译器优化的后的,就是上文所说的 RVO 和 NRVO

    3、编译器优化

    g++ 可以使用参数 -fno-elide-constructors 来关闭优化,CMakeList 使用以下代码关闭

    add_compile_options(-fno-elide-constructors)
    

    或者

    set(CMAKE_CXX_FLAGS “-fno-elide-constructors ${CMAKE_CXX_FLAGS}”)
    

    如果我们关闭编译器的优化,最后输出的结果应该是

    constructor 12		//getTest()函数内构造test对象
    copy constructor 12	//getTest()的返回值不能是test对象,需要一个临时变量,使用test对象拷贝构造临时对象_test
    destructor 12		//getTest()返回,test对象被析构
    copy constructor 12	//main()函数使用test2变量接收临时对象_test
    destructor 12		//临时对象_test被析构
    print 12		//print()调用
    destructor 12		//main()函数内test2对象被析构
    

    不难理解,我的记忆没错,根据C++语法确实应该有拷贝构造,只不过是编译器优化了

  • 相关阅读:
    JS 加载html 在IE7 IE8下 可调试
    css 实现三角形 实现过程
    JSONP 理解 和 实例 讲解
    js 闭包 理解
    常见input输入框 点击 发光白色外阴影 focus
    常用垂直居中 随窗口改变一直居中布局 实例
    修改wampserver 默认localhost 和phpmyadmin 打开链接
    validate jquery 注册页面使用实例 详解
    mysql 查询表结构 查询索引
    wampserver 绑定域名 外部可以正常访问
  • 原文地址:https://www.cnblogs.com/sherlock-lin/p/15428456.html
Copyright © 2020-2023  润新知