2013-02-23 26 views
0

我已經使用了boost :: variant一段時間,現在我正在試圖弄清楚它是如何在內部工作的。我寫了一個簡單的測試,我無法理解結果。這裏是(簡化)boost ::變體對象構造計數VS銷燬計數

struct my_type 
{ 
    my_type(){ cout << (size_t)this << " construction"; } 
    ~my_type(){ cout << (size_t)this << " destruction"; } 
}; 

int main() 
{ 
    variant<int, my_type> x; 
    x = my_type(); 
} 

這樣的程序的輸出是

140736940365327 construction <-- A 
140736940365236 destruction <-- ? 
140736940365327 destruction <-- A 
140736940365332 destruction <-- ? 

憑啥析構函數不調用多次構造?由於析構函數是通過堆調用的,我知道這可能不是段錯誤,但在我看來,這種行爲是危險的。我錯過了什麼嗎?這與boost :: variant的「備份」機制有關嗎?

+2

向您的課堂添加複製構造函數。 – Mat 2013-02-23 12:22:23

回答

2

你只定義了一個默認構造函數,當然也可以用各種參數調用構造函數。由於您沒有明確定義複製構造函數(構造函數採用const my_type&),編譯器會爲您隱式生成一個。如果您添加您自己的拷貝構造函數,你應該看到它是用來構建另外兩個神祕對象:

struct my_type 
{ 
    my_type(){ cout << (size_t)this << " construction"; } 
    my_type(const my_type&){ cout << (size_t)this << " copy construction"; } 
    ~my_type(){ cout << (size_t)this << " destruction"; } 
}; 

事實上,如果您使用的是C++編譯器11,一個隱式生成移動構造函數將負責一些新的對象。如果你像上面提供了一個拷貝構造函數,那麼隱式移動構造函數就不會再生成了,所以它們都顯示爲拷貝結構。但是,如果您也提供移動構造函數,則會發現它被稱爲:

struct my_type 
{ 
    my_type(){ cout << (size_t)this << " construction"; } 
    my_type(const my_type&){ cout << (size_t)this << " copy construction"; } 
    my_type(my_type&&){ cout << (size_t)this << " move construction"; } 
    ~my_type(){ cout << (size_t)this << " destruction"; } 
}; 
+0

那麼默認的構造函數是在我沒有定義的時候隱式調用的? – neodelphi 2013-02-23 12:27:21

+0

@neodelphi是的,編譯器爲你隱式生成一個拷貝構造函數,如果你沒有定義它的話。 – 2013-02-23 12:28:33

+0

謝謝,解釋一下吧! – neodelphi 2013-02-23 12:29:50