2010-04-02 54 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. 

我无法想象的任何容器中的任何成员函数,将无效的迭代器到特定元件,但不是指向那些相同元素的指针或引用,但我想我可能会误解。

最好查看标准对特定容器和成员函数的说明。