zoukankan      html  css  js  c++  java
  • 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++语法确实应该有拷贝构造,只不过是编译器优化了

  • 相关阅读:
    C# 控制反转
    控制反转和依赖注入
    C#中使用AOP
    jquery ajax
    python(7)- 小程序练习:循环语句for,while实现99乘法表
    007所谓性格与条件并不是成功的阻碍,懦弱才是
    006学习有可能速成吗
    005自学与有人带着哄着逼着学的不同在于自学是一种成熟的自律
    005单打独斗意味着需要更好地管理自己
    004真正的教育是自我教育,真正的学习是自学
  • 原文地址:https://www.cnblogs.com/sherlock-lin/p/15428456.html
Copyright © 2011-2022 走看看