2014-03-07 68 views
1
#include <iostream> 
using namespace std; 

int gc = 0; 
struct A { 
    int id; 
    A():id(gc++) { cout << "Constructed #" << id << "\n"; } 
    A(const A& b):id(gc++) { cout << "Copying from " << b.id << " to " << id << "\n"; } 
    ~A() { cout << "Destructed #" << id << "\n"; } 
}; 
A f() { 
    A a; 
    cout << "Exiting f()" << "\n"; 
    return a; 
} 
int main() { 
    A b = f(); 
    cout << "Exiting main()" << "\n"; 
    return 0; 
} 

產生的輸出(無優化(-O0),並使用任一這些編譯的:克++ 4.6.3,克++ 4.8.1,鐺++ 3.0在Ubuntu):NRVO - 這個程序的輸出是否定義良好?

Constructed #0 
Exiting f() 
Exiting main() 
Destructed #0 

我的用於複製的猜測沒有被調用的構造函數(儘管它具有可觀察的副作用),並且在f()中沒有被破壞的對象a)是NRVO(類似於https://stackoverflow.com/a/3906038/1857518中描述的情況)。

我的問題:

  1. 這是程序的C++標準以及指定的輸出?
  2. 如果(1)爲真,則該以下情況下,它是如下之一:
    • 輸出將總是精確地是這
    • 存在着一個法律&有限集合的輸出,也就是說,Out(例如即|Out| > 1)。並且符合的編譯器可以生成集合Out中的任何一個。如果是這種情況,那麼設置Out看起來像什麼。

回答

2

你這種行爲看什麼叫copy elision

1.該程序的輸出是否完全由C++標準規定?

是的,允許編譯器優化複製副作用爲這種情況。

2.輸出將始終正好是這個

號如前所述,編譯器允許優化複製行爲,但是並不一定需要做到這一點。

因此,您不能依賴任何副作用到位或刪除返回的「副本」。另見這篇文章:Is it possible to ensure copy elision?

+0

後續問題:是否有可能創建臨時文件?我問的原因是因爲這個頁面http://msdn.microsoft.com/en-us/library/a8kfxa78.aspx說'只有當你的程序沒有將返回值複製到一個對象時才創建這些臨時對象。這是MSVC++決定做的事情,還是由C++標準規定的東西? – abi

+0

@abi _'是MSVC++決定做的事情還是由C++標準強制的東西?'我首先說,如果沒有賦予AFAIR左值,那麼標準根本不會聲明實例化臨時對象。如上所述:You **不應該依賴複製構造函數在這種情況下實現的副作用。 –