怪我咯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
, 其實還是四個物件.
高洛峰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