2011-09-23 91 views
16

如下因素代碼顯示不期望的輸出:STL Vector是否調用未分配對象的析構函數?

class test 
{ 
    public: 
    test() 
    { 
     std::cout << "Created" << (long)this << std::endl; 
    } 
    ~test() 
    { 
     std::cout << "Destroyed" << (long)this << std::endl; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    std::vector<test> v; 
    test t; 
    v.push_back(t); 

    return EXIT_SUCCESS; 
} 

執行時它顯示:

Created-1077942161 
Destroyed-1077942161 
Destroyed674242816 

我認爲第二個「破壞」輸出不應該存在。當我不使用該向量時,結果是一個Created和一個Destroyed行如預期。這種行爲是否正常?

(這與GCC編譯FreeBSD系統上)

+3

+1 [SSCCE](http://sscce.org/) – Flexo

+3

要打印指針,最好將其轉換爲void指針:'std :: cout <<(void *)this << std :: endl ;'。 –

+0

同時返回'EXIT_SUCCESS'是可選的。你可以在'main'中省略返回值,它會返回'0'(這將變成任何意味着你的平臺的「正常終止」) –

回答

31

一切都是理所應當的:有局部變量t,這被創建,然後銷燬在main()末,並有v[0],它得到在main()的末尾創建並銷燬。

您看不到v[0]的創建,因爲這是通過複製或移動構造函數(您的測試類未提供)來實現的。 (所以編譯器提供一個給你,但沒有輸出。)


爲了測試它的方便編寫一次爲自己和所有的測試類,它包含了所有可能的構造函數,析構函數,分配和交換運營商並在每個中打印診斷行,以便您可以目睹在容器和算法中使用對象時的行爲。

+0

它不能是「移動構造函數」。 – Nawaz

+0

@Namaz:對。要使用移動構造函數,你必須說eitehr'v.push_back(std :: move(t))'或'v.push_back(test())'。不過,兩者都會創建類似的消息序列。 –

29
#include <cstdlib> 
#include <vector> 
#include <iostream> 

class test 
{ 
    public: 
    test() 
    { 
     std::cout << "Created " << (long)this << std::endl; 
    } 
    test(const test&) 
    { 
     std::cout << "Copied " << (long)this << std::endl; 
    } 
    ~test() 
    { 
     std::cout << "Destroyed " << (long)this << std::endl; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    std::vector<test> v; 
    test t; 
    v.push_back(t); 

    return EXIT_SUCCESS; 
} 

輸出:

Created -1076546929 
Copied 147865608 
Destroyed -1076546929 
Destroyed 147865608 

std::vector::push_back複製t對象,你可以看到拷貝構造函數通過上面的代碼中被調用。

2

該矢量持有t的副本,因此在撥打push_back後,您有兩個版本的t ...一個在堆棧中,一個在向量中。由於矢量版本是由複製構造者創建的,因此您不會看到該對象的「創建...」提示...但它仍然必須在矢量容器超出範圍時銷燬,因此您得到兩個「被毀壞......」的消息。

相關問題