2013-10-26 103 views
1

我已經採取了看看this presentation,在滑動379,它顯示了下面的代碼(有一些小的改動):爲什麼代碼調用析構函數兩次?

#include <iostream> 
using namespace std; 

struct A 
{ 
    A() { cout << "A()" << endl; } 
    A(int v) { cout << "A(int)" << endl; } 
    ~A() { cout << "~A()" << endl; } 
}; 

struct X 
{ 
    X(int v) { a = v; } 
    X(long v) : a(v) {} 
    A a; 
}; 

int main() 
{ 
    cout << "bad style:" << endl; 
    { X slow(int(2)); } 
    cout << "good style:" << endl; 
    { X fast(long(2)); } 
} 

輸出爲:

bad style: 
A() 
A(int) 
~A() 
~A() 
good style: 
A(int) 
~A() 

(此代碼是在我的機器上運行,用g ++編譯)

現在,我明白了爲什麼構造函數會在壞風格中調用兩次,但爲什麼析構函數會這樣做呢?

+1

好,如果構造函數被調用兩次,這意味着有兩個對象要銷燬。 – GManNickG

+0

如果構造函數被調用兩次,則構造兩個對象。所以需要銷燬兩個物體。 – juanchopanza

回答

8
X(int v) { a = v; } 
//   ^^^^^ 

帶下劃線的行是一個賦值。沒有operator=需要intv),但存在從intA的隱式轉換。因此,構造一個A類型的臨時對象並將其傳遞給編譯器爲您生成的賦值運算符。它在後來被破壞(在完成表達式被創建之後),並且還有你沒有想到的第二個析構函數。

+1

我不知道任務可以調用構造函數... o_O – 0x499602D2

1

的邏輯是

Instantiate a Class ... +1 [Constuctor] 
Desinstantiate a Class ... -1 [Destructor] 

當該對象流出的範圍或顯式地刪除析構函數被稱爲一類對象。

所以你可以期望這些類的析構函數被稱爲這些類被創建的次數相等。

0

介紹

還有就是要考慮,在C運行時的構造析構函數& ++額外的事情。

你是在聲明一個靜態分配的對象還是一個動態分配的對象?

靜態分配

#include <iostream> 
using namespace std; 

class A { 
public: 
    // constructors 
    A() { cout << "A()" << endl; } 
    A(int v) { cout << "A(int)" << endl; } 

    // destructors 
    ~A() { cout << "~A()" << endl; } 
}; 

class X { 
public: 
    // constructors 
    X(int v) { a = v; } 
    X(long v) : a(v) {} 

    // variables 
    A a; 
}; 

int main() 
{ 
    cout << "bad style:" << endl; 
    X slow(int(2)); 

    cout << "good style:" << endl; 
    X fast(long(2)); 
} 

動態分配

#include <iostream> 
using namespace std; 

class A { 
public: 
    // constructors 
    A() { cout << "A()" << endl; } 
    A(int v) { cout << "A(int)" << endl; } 

    // destructors 
    ~A() { cout << "~A()" << endl; } 
}; 

class X { 
public: 
    // constructors 
    X(int v) { a = new(v); } 
    X(long v) : { a = new(); *a = v; } 

    // destructors 
    ~X() { delete a; } 

    // variables 
    A* a; 
}; 

int main() 
{ 
    cout << "bad style:" << endl; 
    X slow = new X(int(2)); 

    cout << "good style:" << endl; 
    X fast = new (long(2)); 

    // do something else with "X" 

    delete slow(); 
    delete fast(); 
} 

摘要

靜態分配的變量自動調用析構函數,而動態分配的變量,美se指針,你需要顯式調用析構函數。

** **外

如果您以前使用另一種面向對象的語言,或是從C++切換到另一個,這個考慮,因爲也許不同的處理是很重要的。

1

你是「隱式類型轉換」的受害者。嘗試「明確的」添加到您的構造函數和會看到什麼是錯在你的代碼(將在前者的隱式轉換的地方停止編譯):

struct A 
{ 
    explicit A() { cout << "A()" << endl; } 
    explicit A(int v) { cout << "A(int)" << endl; } 
    ~A() { cout << "~A()" << endl; } 
}; 

這裏有一個解釋: http://en.cppreference.com/w/cpp/language/implicit_cast

相關問題