首頁  >  問答  >  主體

c++析构函数可以使一个return-by-value的函数少执行一次拷贝构造函数,是什么原因?

PHPzPHPz2715 天前646

全部回覆(2)我來回復

  • 怪我咯

    怪我咯2017-04-17 13:19:04

    原因在於優化.
    先來分析你的程式, a1是一個實例, a2是一個, getTest傳參是傳值那麼會有一個Temp1, getTest又有一個return Temp2.​​ 所以一共應該是四個對象.

    但是, 編譯器會有優化, 甚至在你禁止優化的時候也會有一點點優化. 例如getTest的返回值, 本來按照語義是需要調用operator=, 實際上編譯器通常是直接調用CTest1(const CTest1&)這個建構子, 把兩次構造最佳化成1次.

    你那個程式碼, 把析構函式裡面的cout註解掉, 就會發現只建構了3次. 因為析構函式裡面什麼都沒有的話, 編譯器開啟那個最佳化, 對你的程式碼功能上就沒有任何影響. 但是你開cout的話, 一旦優化掉的話, 程式碼的功能可能就不正確了.

    你刪掉析構函式裡面的cout, 用gcc編譯, 加參數-O0 -fno-elide-constructors, 其實還是四個物件.

    回覆
    0
  • 高洛峰

    高洛峰2017-04-17 13:19:04

    CTest1 getTestObj(CTest1 obj)
    {
        return obj; /* copy */
    }
    
    int main()
    {
        CTest1 a1; // construct             
        CTest1 a2 = /* copy */ getTestObj(a1/* copy */);
        return 0;
    }

    關於回傳值有一種對編譯器來說省事的方式,叫做回傳值最佳化(RVO - return value optimization)。編譯器會省略一步物件的COPY建構調用,不知道LZ用的什麼編譯器,在gcc(4.8.3)上面是預設開啟的,就是說結果是這樣的:

    Constructor of CTest1:0
    Copy constructor of CTest1:1
    Copy constructor of CTest1:2
    //如果去掉注释 就会打印下面三句话
     destroy id:1 
     destroy id:2
     destroy id:0
    

    回覆
    0
  • 取消回覆