2009-09-05 62 views
12

我一直對STL容器(vector,list,map ...)如何存儲值感到困惑。他們是否存儲對我傳入的值的引用,還是複製/複製構造+存儲這些值本身?STL:存儲引用或值?

例如,

int i; 
vector<int> vec; 
vec.push_back(i); 
// does &(vec[0]) == &i; 

class abc; 
abc inst; 
vector<abc> vec; 
vec.push_back(inst); 
// does &(vec[0]) == &inst; 

感謝

+5

你有什麼看起來像我的工作代碼,將測試答案(一個小的變化,使評論有條件)。運行它並看看!我很確定他們複製構建和存儲。 – 2009-09-05 06:33:49

回答

18

STL容器拷貝構造,你在傳遞和存儲的值。如果你想存儲在一個容器對象沒有複製它們,我會建議存儲一個指向容器中的對象的指針:

class abc; 
abc inst; 
vector<abc *> vec; 
vec.push_back(&inst); 

這是最合乎邏輯的實現容器類的方法,以防止意外地將引用存儲在已停用的堆棧幀上。試想一下:

class Widget { 
public: 
    void AddToVector(int i) { 
     v.push_back(i); 
    } 
private: 
    vector<int> v; 
}; 

存儲一個參考i將是危險的,因爲你會從它的定義方法返回後會引用一個局部變量的存儲位置。

+5

您不能創建用C++存儲引用的創建容器。傳遞給容器的類型參數必須是可分配的。引用是不可賦值的,它們是用一個對象初始化的,但是在構造之後不能賦給一個引用不同的對象。因此引用類型不符合容器內使用的類型要求。如果你想擁有相同的語義(或者儘可能接近它),你必須提供一個引用包裝(boost :: ref/boost :: cref) – 2009-09-05 09:44:15

+3

@dribeas:這個答案解釋了_Why not_,通過解釋假設的風險實現。 – MSalters 2009-09-07 10:53:16

4

這取決於你的類型。如果它是一種簡單的值類型,而且價格便宜,那麼存儲值可能就是答案。另一方面,如果它是一個引用類型,或者複製的代價很高,最好存儲一個智能指針(不是auto_ptr,因爲它的特殊複製語義會阻止它被存儲在一個容器中,請參閱shared_ptr)。使用簡單的指針可能會導致內存泄漏和訪問釋放的內存,而引用後者會導致後者冒險。智能指針可以避免這兩種情況。

+2

+1使用容器內的智能指針來處理內存。另一種選擇可能是使用類似Boost指針容器的庫來處理資源釋放 – 2009-09-05 09:46:16

+5

這不是OP所要求的。他想知道容器類放置在容器中時它們是否自己複製該值。答案是,是的,他們這樣做 - 這就是爲什麼存儲指針可以很好,如果有問題的特定類型的複製是昂貴的。 – 2009-09-05 10:19:11

+2

如果你知道自己在做什麼並且自己清理完畢,那麼存儲裸指針就非常好。 – 2009-09-05 15:31:30