2010-02-07 57 views
0

幫助這裏是代碼:需要與理解STL向量(在郵件的正文簡單的代碼)

#include <vector> 
#include <iostream> 

class A 
{ 
public: 
    A() { std::cout << __FUNCTION__ << "\n"; } 
    ~A() { std::cout << __FUNCTION__ << "\n"; } 

    A& operator=(const A&) { std::cout << __FUNCTION__ << "\n"; return *this;} 
}; 

int main(int argc, char* argv[]) 
{ 
    std::vector<A> as; 
    A a; 
    as.push_back(a); 
    as.push_back(a); 
    return 0; 
} 

這裏是我得到的輸出:

A::A 
A::~A 
A::~A 
A::~A 
A::~A 

我理解的輸出第一行是從創建'a'時從調用到c-tor。對d-tor的一個要求也屬於a。 另外三個對A ::〜A()的調用呢,它們來自哪裏? 爲什麼有更多的d-tor調用比c-tor的調用要多? 容器在向其元素添加副本時如何克隆「a」? 最後,是輸出實現定義還是還有其他可能的輸出?

回答

2

要了解發生了什麼,你缺少在一種方法:

A(const A&) { std::cout << __FUNCTION__ << "(const A&)\n"; } 

然後你可以看到輸出:

A() 
A(const A&) 
A(const A&) 
A(const A&) 
~A 
~A 
~A 
~A 

什麼發生的是,對於每一個的push_back矢量分配一個新的連續數組,複製舊內容並銷燬它。如果你計算,第一個拷貝構造函數是第一個push_back,第二個和第三個是下一個push_back。第一個析構函數用於第二個push_back,第二個析構函數用於銷燬矢量,最後一個用於銷燬變量a。

順便說一句,這是完全實現定義的,因爲它可以通過塊進行分配,這將防止相當多的複製/銷燬。你甚至可以通過使用vector::reserve(size_type n)自己塊。

3

您需要添加一個拷貝構造函數:

A(const A&) { std::cout << __FUNCTION__ << "\n"; } 

的載體,像所有其他標準庫容器,商店副本 - 這些副本與拷貝構造函數取得。不過,您應該知道,有幾個地方編譯器可以用來避免複製構建,甚至可以製作額外的副本,因此您的輸出可能不完全符合您的期望。

0

正如我確信你意識到你正在堆棧上創建你的「A」對象,然後將它們複製到數組中(正如其他答案所暗示的),暗示使用拷貝構造函數。

如果你的A對象是擁有數據的真實數據對象,或者難以複製的複雜狀態,你可能需要考慮在你的數組中存儲指針,而不是直接存儲對象。你需要自己管理記憶,但這是一個值得考慮的問題。

int main(int argc, char* argv[]) 
{ 
    std::vector<A*> as; 
    A *a = new A(); 
    as.push_back(a); 
    as.push_back(a); 
    return 0; 
} 

你會看到輸出:

A() 

由於只有一個實例對象已經創建和數組只是存儲指針的副本。很顯然,在某些時候,您需要通過其中一個指針刪除對象本身,以確保最終獲取內存。