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

  • 相关阅读:
    模拟_大数字符串(HDU_2054)
    DP_字串匹配(HDU_1501)
    动态字典树_字串标记查找+大数(HDU_4099)
    动态字典树_字串查找匹配(HDU_1075)
    动态字典树+DFS(HDU_1298)
    动态字典树_拆分查找(HDU_1247)
    动态字典树_统计前缀子串(HDU_1251)
    动态字典树_统计子串(HDU_2846)
    字典树讲解
    HTML5语义标签的实践(blog页面)
  • 原文地址:https://www.cnblogs.com/sherlock-lin/p/15428456.html
Copyright © 2011-2022 走看看