2012-03-21 38 views
0

我試圖在以下守則:第一次破壞來自哪裏?

#include <iostream> 
#include <vector> 

using namespace std; 

class A 
{ 
public: 
    virtual void f(){cout<<"A"<<endl;} 
    virtual ~A(){cout<<"destruct A"<<endl;} 
}; 

int main() 
{ 
    A o1,o2; 
    vector <A > O; 
    O.push_back(o1); 
    cout<<"1"<<endl; 
    O.push_back(o2); 

cout<<"test"<<endl; 
return 0; 
} 

結果竟然是:

1 
destruct A 
test 
destruct A 
destruct A 
destruct A 
destruct A 

弄不清楚其中,第一析構函數得來的。

回答

1

我們不得不打印語句拷貝構造函數後,我們得到這個:

constructor A(0x7fff6e21e800) 
constructor A(0x7fff6e21e7f8) 
copy A(0x10e700910: From 0x7fff6e21e800) 
1 
copy A(0x10e700920: From 0x10e700910) 
copy A(0x10e700928: From 0x7fff6e21e7f8) 
destruct A(0x10e700910) 
test 
destruct A(0x10e700920) 
destruct A(0x10e700928) 
destruct A(0x7fff6e21e7f8) 
destruct A(0x7fff6e21e800) 

所以,現在讓我們看看代碼:

int main() 
{ 
    A o1, 
    // constructor A(0x7fff6e21e800) 
     o2; 
    // constructor A(0x7fff6e21e7f8) 
    vector <A > O; 
    O.push_back(o1); 
    // copy A(0x10e700910: From 0x7fff6e21e800) 
    cout<<"1"<<endl; 
    // 1 

    O.push_back(o2); 
    // copy A(0x10e700920: From 0x10e700910) // O needs to expand. 
               // So a new range is created and the old value 
               // copied from the old range to the new range. 

               // Now we push o2 into the vector 
    // copy A(0x10e700928: From 0x7fff6e21e7f8) 

               // Now the old range has to be destroyed. 
    // destruct A(0x10e700910) 


    cout<<"test"<<endl; 
    // test 


    return 0; 
       // Before we exit destroy the old vector (of two items) 
    // destruct A(0x10e700920) 
    // destruct A(0x10e700928) 

       // Now destroy o2 then o1 
    // destruct A(0x7fff6e21e7f8) 
    // destruct A(0x7fff6e21e800) 
} 
+0

不明白爲什麼「O需要擴展,所以創建一個新的範圍,並將舊值從舊範圍複製到新範圍。」 – 2012-03-21 14:20:34

+0

當首次創建「O」時,它可能創建的容量爲1.在第一個元素被推入後,它現在已滿。但是矢量會自動擴展,並且一旦完成,它必須將舊數據範圍內的所有元素複製到新數據範圍。如果在開始推送元素之前調用'O.reseve()',那麼這個額外的副本將會消失。 – 2012-03-21 15:53:02

1

使構造函數和析構函數打印對象的內存地址,這樣你就可以按照它的生命週期:

virtual void f() { cout << "A: " << std::hex << this << endl; } 
virtual ~A(){ cout << "destruct A: " << std::hex << this << endl; } 
+0

你還需要做的拷貝構造函數。 – 2012-03-21 02:54:19

+0

觀察得很好,@Loki – karlphillip 2012-03-21 02:57:23

5

你的矢量重新分配的第二次調用的push_back內存緩衝區。這需要將那裏的對象複製到新緩衝區,並且原始對象被銷燬。

如果在插入任何對象之前調用O.reserve(2),那麼將爲您的向量賦予足夠的空間以使兩個對象相關。所以它不需要重新分配,並且在main結束之前你不應該看到任何破壞。從技術上講,如果你的編譯器吮吸並製造不必要的副本,那麼可能會有更多的破壞。但是,從目前爲止所顯示的情況來看,似乎沒有這樣做。