2016-06-09 36 views
1

我正準備上拷貝構造函數的演講,發現這個:拷貝構造函數返回臨時對象

MyClass myFunction() 
{ 
    MyClass mc; 
    return mc; 
} 

的聲明說:

如果我們調用myFunction的,那麼C++將創建一個新的myClass的對象 當myFunction返回時,它初始化爲mc。因此,儘管您的代碼 可能會像將對象從 myFunction中透明地移動到您的代碼的其餘部分,但實際上它會臨時製作 副本。

我想聲明MyClass mc;將創建該對象,並返回窗體函數而不是任何臨時對象。 我哪裏錯了?有人可以詳細說明該語句能夠輕鬆理解嗎?

+8

NRVO(命名返回值優化)複製構造函數的elides(應用時)。 – Jarod42

+0

https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization – CoryKramer

+0

並移動構造函數(如果可用)完成此舉。我認爲,這個講座非常過時,而且根本不清楚。 – SergeyA

回答

1

比方說,你有這樣的代碼:

#include <iostream> 
using namespace std; 

class MyClass 
{ 
public: 

    int *v; 

    MyClass() 
    { 
     v=new int[5]; 
     for(int i=0;i<5;i++) v[i]=i; // x will look like : 0,1,2,3,4 
    } 

    ~MyClass() 
    { 
     cout<<"Destructor called! Now v is deallocated! \n"; 
     delete[] v; 
    } 
}; 

MyClass myFunction() 
{ 
    MyClass mc; 
    return mc; 
} 

int main() 
{ 
    MyClass x; 

    x=myFunction(); 

    cout<<x.v[2]<<'\n'; //it may or may not print the right thing 

    return 0; 
} 

正如你所看到的,myFunction像你說的返回對象mc。但是你也知道mc的析構函數將在mc超出範圍時被調用 - mcmyFunction內聲明,所以析構函數將在函數執行後被調用並釋放內存(delete[] v)。內存被釋放,但值仍然在內存中!所以,儘管x=myFunction();可以工作,但您將有一個內存v指向的對象被釋放!所以,cout<<x.v[2]<<'\n';可能不打印正確的東西。如果你編譯代碼,它會可能打印正確的值(2),因爲內存沒有被覆蓋,但如果你要在cout語句之前做一些更多的分配,或者在使用你的操作系統一段時間後,你會看到打印的值不正確/崩潰,因爲內存將被其他程序覆蓋。 v仍然指向那個內存塊,但它不知道那裏有什麼,因爲內存被解除分配。

myFunction:V> - |0|1| 2 |3|4|...

退出myFunction後:V> - |0|1| 2 |3|4|.....

一些內存分配後:V> - |a|1| b |@|%|3|7|2|1|*|!|......

+0

先生二懷疑:函數調用後內存被析構函數釋放。所以x有一個指向垃圾的指針。如果不是那麼在x離開範圍析構函數被再次調用然後它給出之後,cout語句應該理想地給出錯誤內存損壞。其次是這裏應用臨時對象概念的地方。 –

+0

錯過了你正在談論的成員指針。 – kfsone

+0

先生,我已經執行了上面的代碼在Linux和g ++編譯器它正確打印cout之後,它會產生內存錯誤。我想知道它爲什麼正確打印第一次,而理論上刪除操作符解除分配內存。 –

3

我想聲明MyClass mc;將創建對象

正確。

並且它返回表單函數沒有任何臨時對象。

我不完全理解你的聲明,所以我不能告訴你是否已經出了問題,但是這是發生了什麼:

mc是一個局部變量。當函數退出時局部變量被銷燬。在它被銷燬之前,臨時對象從它被複制初始化。臨時對象然後從函數返回。

額外知識1:自C++ 11以來,如果可能,臨時文件將被複制初始化爲移動

額外知識2:標準顯式允許編譯器跳過複製/移動,而是在呼叫站點構造對象。這種優化被稱爲(命名)返回值優化,是一種複製elision的形式。儘管如此,您無法返回既不可複製也不可移動的對象。這是因爲不需要實施C++來執行NRVO。

+0

你的答案似乎自相矛盾。 「X發生」。 「X不允許發生」。 – juanchopanza

+0

@juanchopanza爲了更容易解釋OP詢問的陳述,我避免提及例外。瞭解複製省略對於瞭解按價值返回並不是必需的。但在瞭解價值迴歸之前瞭解複製瑕疵容易導致誤解。 – user2079303