2015-06-28 84 views
0

我試着運行下面的代碼,我不明白何時以及爲什麼析構函數在myA=foo(myOtherB)處被調用。函數調用完成後無法解釋析構函數返回對象

我的問題是,在foo函數返回A對象後,從'input'複製構造它並打印一個複製函數operator=被調用打印'Aop',然後析構函數被調用打印A dtor。

爲什麼析構函數在此時調用而不是在operator=調用之前的返回之後?

另一個問題,我有是,如果我使用return A(2)代替return input 構造函數不會被調用打印的男星......

誰能解釋一下嗎?我的代碼是一個有點複雜遺憾。

#include <iostream> 

using namespace std; 

class A 
{ 
    public: 
     int x; 
     A(){ cout<<"A ctor"<<endl; } 
     A(const A& a){cout<<"A copyctor"<<endl; } 
     virtual~A(){ cout<<"A dtor"<<endl;} 
     virtual void foo(){ cout<<"Afoo()"<<endl;} 
     virtual A& operator=(const A&rhs){cout<<"Aop="<<endl; } 
     A(int _x) 
     { 
      x=_x; 
     } 
}; 


class B:public A 
{ 
    public: 
     B(){ cout<<"B ctor"<<endl; } 

     virtual~B(){ cout<<"B dtor"<<endl; } 
     virtual void foo(){ cout<<"B foo()"<<endl; } 
    protected: 
     A mInstanceOfA; 

}; 

A foo(A& input) 
{ input.foo(); return input; //return A(2); does not call the A constructor } 



int main() 
{ 

    B myOtherB; 
    A myA; 
    myA=foo(myOtherB); 

} 

回答

2
return A(); 

這叫做most vexing parse
你不是調用A的構造函數(不是創建一個新的實例),而是聲明一個返回A的函數(請閱讀鏈接以獲取更多的可能更正確的解釋)。

您可以通過調用構造函數:

return A{2}; 

這就是所謂的Uniform initialization syntax(C++ 11或更高版本)


A myA; 
myA=foo(myOtherB); 

在這種情況下,首先要創建一個新的A對象( myA),然後將該變量分配給foo函數的返回值。
由於第二行,這將調用賦值運算符。
您複製foo返回到myA變量的值。

當已經創建的myA變量重新分配時,舊值將被銷燬,因此調用destructor

我想你追求的是以下幾點:

A myA = foo(myOtherB); 
+0

我想我理解構造函數的一部分,但我沒有實際分配任何東西給myA,因爲operator =只是執行一個cout ...所以爲什麼析構函數被調用,因爲沒有重新賦值myA?Does =總是意味着重新賦值no你在運算符=函數中做什麼? –

0

您可以通過值返回,這意味着你返回值被複制到一個臨時對象,一個是後破壞。

+0

爲什麼在調用operator =之後它會被破壞? '以後'是什麼意思? –

+0

@matts該函數按值返回,這意味着編譯器會爲返回的對象創建一個臨時對象,然後該賦值操作符將使用此臨時對象,並且一旦賦值表達式結束,該臨時對象就會被銷燬。 –

0

我試圖運行下面的代碼,我不知道什麼時候,爲什麼 不析構函數被調用在該行妙= FOO( myOtherB)。

因爲RAII,析構函數會在主函數的最後一個大括號之前被調用。

爲什麼析構函數在此時調用而不是在 之後返回operator = call之前的返回?

我已經回答了上面這個問題,對象範圍的問題。每當你的對象超出範圍,析構函數將被調用。

另一個問題,我有是,如果我使用返回A(2),而不是返回 輸入構造函數不會被調用打印的男星......

A foo(A& input) 
{ input.foo(); return input; //return A(2); does not call the A constructor } 

您正在返回一個現有的對象輸入作爲您的函數接收的參考,因此係統無需通過調用構造函數來創建對象。

+0

析構函數不會在main的最後一個大括號處被調用。如果我在最後一個大括號之前放置了一個getchar(),則在調用getchar()之前調用析構函數() –

+0

@matts編譯器可以優化語句的順序,除非沒有特定你的程序的行爲改變。即使析構函數在影響後的getchar()之前或之後調用相同。 – Steephen

相關問題