【问题标题】:Pointers into elements in a container指向容器中元素的指针
【发布时间】:2011-02-03 17:48:17
【问题描述】:

假设我有一个对象:

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

我有一个包含Foos 的 STL 容器,可能是一个向量,我拿了

// Elsewhere...

vector<Foo> vec;

vec.push_back(Foo(4));

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

这是一个糟糕的主意,对吧?

原因是vector 将其元素存储在某个动态分配的数组中,最终,如果您添加足够多的元素,它将不得不分配另一个数组,复制原始数组的所有元素,并删除旧数组。在那之后,p 指向垃圾。这就是为什么vector 上的许多操作会使迭代器无效的原因。

似乎可以合理地假设使容器中的迭代器无效的操作也会使指向容器元素的数据成员的指针无效,并且如果操作使迭代器无效,这些指针仍然是安全的。然而,许多合理的假设是错误的。这是其中之一吗?

【问题讨论】:

  • @Brian:我认为 Pillsy 在语义上是正确的,如果不是在语法上。

标签: c++ stl pointers


【解决方案1】:

标准规定了此类指针何时失效。当您将 vector 的大小增加到超过 capacity 或添加/删除前面的元素时,对 vector 的引用会死掉。如果您从中间添加/删除,对 deque 的引用将失效。

否则,在底层对象的生命周期内,引用和迭代器是安全的。

【讨论】:

  • 好收获。同样适用于vector
  • '列表中的迭代器可能因拼接而失效'你是什么意思?列表中的迭代器只有在它们引用的元素从包含列表中删除时才会失效,并且在那个特定时刻,对这些元素的引用也会失效。树案例也是如此,“重新链接”是什么意思?当它们引用的元素从树结构中删除时,映射或集合的迭代器将失效,就像对这些对象的引用一样。树的重新平衡不会影响迭代器的有效性。
  • @David: §23.2.2.4 说list::splice 使所有迭代器对更改所有权的元素无效。不过,您对关联容器是正确的,23.1.2/8。我不知道我从哪里得到这个想法。
  • 这就是我的意思:第 23.2.2.4 节的措辞非常明确:“使 ... 迭代器和 引用 无效。每当迭代器失效时,对元素的引用也会在所有容器中失效。迭代器在这方面与引用没有什么不同。在每种情况下,其迭代器/引用无效的元素都是从列表中删除的元素。
  • @David:啊,我现在明白了,抱歉。然而,list::splice 不应该(不能?)实际上做任何事情来触摸这些对象......嗯,N3035 要求指针和迭代器保持有效,尽管已经“传送”。我想这根本不值得一提。
【解决方案2】:

如果调整向量的大小,内容将通过复制和/或分配有效地重新创建。新包含的对象将(可能)位于不同的位置,因此任何指向 或其成员的指针都将(可能)无效 - 您当然应该假设是这种情况。

【讨论】:

    【解决方案3】:

    是的,你的直觉是正确的。在标准提到迭代器无效的地方,它也倾向于声明引用也无效。

    例如,这里有一些描述vector的“reserve”成员函数的一些效果的部分文字:

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

    我无法想象任何容器的任何成员函数都会使特定元素的迭代器无效,但不会使指向相同元素的指针或引用无效,但我想我可能弄错了。

    最好检查标准对您的特定容器和成员函数的规定。

    【讨论】:

      【解决方案4】:

      您对向量的假设是合理的,因为迭代器可以实现为指针周围的薄包装器。作为指针的替代方法,您可以将偏移量存储到向量。这些将通过插入和擦除无效,但不会通过内存重新分配。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-08
        • 2011-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多