堆棧

2013-04-21 185 views
5

構造函數/析構函數調用順序我有以下簡單的代碼:堆棧

class A 
{ 
    int a; 
public: 
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; } 
    ~A()   { cout << "Destructor a=" << a << endl; } 
    void print() { cout << "Print  a=" << a << endl; } 
}; 

void f() 
{ 
    A a(1); 
    a.print(); 
    a = A(2); 
    a.print(); 
} 

int main() 
{ 
    f(); 
    return 0; 
} 

輸出是:

Constructor a=1 
Print  a=1 
Constructor a=2 
Destructor a=2 
Print  a=2 
Destructor a=2 

我發現有與a=2 2次析構函數調用,並沒有與a=1而每個案例都有一個構造函數調用。那麼在這種情況下叫做構造器和析構器呢?

+1

你爲什麼期望使用'a = 1'的析構函數? – juanchopanza 2013-04-21 09:55:50

+2

您是否發現了臨時的「A」值?它活不了很長時間。 – 2013-04-21 09:56:55

+0

我現在發現了Kerrek。哇,答案正在涌入。我清楚地知道。感謝大家。 – SolidSun 2013-04-21 10:10:00

回答

2

這是因爲你不破壞A(1)你分配A(2)它,讓我們來擴展你的例如添加assign operator

class A 
{ 
    int a; 
public: 
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; } 
    ~A()   { cout << "Destructor a=" << a << endl; } 
    void print() { cout << "Print  a=" << a << endl; } 
    A &operator=(const A &other) { 
     cout << "Assign operator old=" << a << " a=" << other.a << endl; 
     a = other.a; 
    } 
}; 

這將導致到:

[[email protected] tmp]$ ./a.out 
Constructor a=1 
Print  a=1 
Constructor a=2 
Assign operator old=1 a=2 <- This line explains why destructor is not called 
Destructor a=2 
Print  a=2 
Destructor a=2 

如果您有這些實現的一個:

  • 析構函數 - 自毀對象的所有成員
  • 複製構造 - 建築對象的所有成員來自複製構造函數參數中的等價成員
  • 複製賦值運算符 - 在賦值運算符的參數

中分配等效成員中的所有對象成員您應該實現所有這些成員。這叫做rule of three

7
a = A(2); 

將使用默認operator=新的值賦給a,設置它的a::a成員值2。

void f() 
{ 
    A a(1);//a created with int constructor a.a == 1 
    a.print();// print with a.a == 1 
    a = A(2);//Another A created with int constructor setting a.a == 2 and immediately assigning that object to a 
    //object created with A(2) deleted printing 2 it was created with 
    a.print();//a.a==2 after assign 
}//a deleted printing 2 it was assigned with 

你或許應該閱讀有關Rule of three得到更好的理解發生了什麼事情。

4
void f() 
{ 
    A a(1); 
     // Constructor a=1 
    a.print(); 
     // Print  a=1 
    a = A(2); 
     // Constructor a=2 
     // also operator= 
     // Destructor a=2 
    a.print(); 
     // Print  a=2 
     // Destructor a=2 
} 
1

首先構造用於= 1被稱爲

第二打印被稱爲

第三其中創建A(2)已被稱爲它的構造新的對象。

第四這個對象被分配給對象的對象A的這樣數據成員= 2

第五的析構函數對象A(2)被稱爲

第六爲對象調用析構函數

2
void f() 
{ 
    A a(1); // Constructor a=1 (a.a(1) is called) 
    a.print(); // Print a=1 
    a = A(2); // Constructor a=2 (Temporary unnamed object A(2) is constructed) 
       // compiler generated a.operator=(const A&); is called and then 
       // Destructor a=2 (Temporary unnamed object is destroyed. 
    a.print(); // Print a=2 
       // Destructor a=2 (a.~a() is called) 
}