2010-04-02 27 views
4

元件說我有一個目的:指針成在容器

struct Foo 
{ 
    int bar_; 
    Foo(int bar) bar_(bar) {} 
}; 

和我有一個包含Foo S,或許一個矢量STL容器,以及我採取

// Elsewhere... 

vector<Foo> vec; 

vec.push_back(Foo(4)); 

int *p = &(vec[0].bar_) 

這是一個可怕的想法,對吧?

原因是vector會將其元素存儲在動態分配的數組中,最後如果添加了足夠的元素,它將不得不分配另一個數組,複製原始數組的所有元素,並刪除舊的數組。發生這種情況後,p指向垃圾。這就是爲什麼許多vector上的操作會使迭代器無效。

現在看來似乎是合理的假設,會從容器迭代器失效的操作也變得無效指針容器元素的數據成員,而如果操作無效迭代器,這些指針會仍然安全。但是,許多合理的假設是錯誤的。這是他們中的一員嗎?

+0

@Brian:我認爲Pillsy在語義上是正確的,如果不是語法。當你添加到中間時, – quamrana 2010-04-02 14:08:02

回答

11

該標準指定何時這些指針無效。當您將其大小增加至capacity或添加/刪除前一個元素時,參考vector死亡。如果從中間添加/刪除,則對deque的引用無效。

否則,引用和迭代器可以安全地保留底層對象的生命週期。

+0

引用到'deque'中也是無效的... – rlbond 2010-04-02 13:35:11

+0

好的結果。同樣適用於'vector'。 – Potatoswatter 2010-04-02 13:36:04

+0

'迭代器到列表中可能會失效通過拼接'你在這裏意味着什麼?只有當它們引用的元素從包含列表中刪除時,迭代器纔會失效,並且在那個特定時刻,對這些元素的引用也會失效。樹箱也是如此,「重新鏈接」是什麼意思?當引用的元素從樹結構中移除時,迭代器映射或集合中的迭代器將失效,就像引用這些對象一樣。樹的重新平衡不會影響迭代器的有效性。 – 2010-04-02 13:49:17

1

如果矢量調整大小,將通過複製和/或分配有效地重新創建內容。新包含的對象將(可能)位於不同的位置,因此指向該對象或指向其成員的任何指針將(可能)失效 - 您當然應該假設情況如此。

0

您的假設對於向量是合理的,因爲迭代器可以作爲指針周圍的薄包裝來實現。作爲指針的替代,您可以將偏移量存儲到矢量中。這些將通過插入和擦除而失效,但不通過內存重新分配。

1

是的,你的直覺是正確的。如果標準提到迭代器失效,它也傾向於聲明引用也是無效的。

例如,這裏的一些部分文本描述了一些矢量的「儲備」成員函數的效果:

Notes: 
    Reallocation invalidates all the references, pointers, and iterators 
    referring to the elements in the sequence. 

我無法想象的任何容器中的任何成員函數,將無效的迭代器到特定元件,但不是指向那些相同元素的指針或引用,但我想我可能會誤解。

最好查看標準對特定容器和成員函數的說明。