为什么std :: vector :: insert会在插入点之后使所有迭代器无效

Tob*_*ull 6 c++ stdvector

当insert进入std::vectorC++标准时,确保插入点之前的所有迭代器保持有效,只要capacity它没有用完(参见[23.2.4.3/1]或std :: vector迭代器失效).

在插入点保持有效(如果容量没有用尽)之后不允许迭代器的原因是什么?当然,他们会指向一个不同的元素,但(从假设的实现std::vector),仍然可以使用这样的迭代器(例如取消引用它或递增它).

zwo*_*wol 9

您似乎在想一个"无效"迭代器,因为只有一个会在使用时引发崩溃,但标准的定义更广泛.它包括迭代器仍然可以安全地解除引用的可能性,但不再指向它预期指向的元素.(这是观察的特殊情况,"未定义的行为" 并不意味着"您的程序将立即崩溃";它也可能意味着"您的程序将默默地计算错误的结果",甚至"在此实现中不会发生任何明显的错误" ".)

更容易证明为什么这是一个问题erase:

#include <vector>
#include <iostream>
int main(void)
{
    std::vector<int> a { 0, 1, 2, 3, 4, 4, 6 };

    for (auto p = a.begin(); p != a.end(); p++) // THIS IS WRONG
        if (*p == 4)
            a.erase(p);

    for (auto p = a.begin(); p != a.end(); p++)
        std::cout << ' ' << *p;

    std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)

在C++的典型实现中,这个程序不会崩溃,但它会打印0 1 2 3 4 6,而不是0 1 2 3 6打算,因为擦除第一个4 无效的 p - 通过在第二个上推进它4.

您的C++实现可能有一个特殊的"调试"模式,在该模式下,该程序在运行时会崩溃.例如,使用GCC 4.8:

$ g++ -std=c++11 -W -Wall test.cc && ./a.out
 0 1 2 3 4 6
Run Code Online (Sandbox Code Playgroud)

但

$ g++ -std=c++11 -W -Wall -D_GLIBCXX_DEBUG test.cc && ./a.out
/usr/include/c++/4.8/debug/safe_iterator.h:307:error: attempt to increment 
    a singular iterator.

Objects involved in the operation:
iterator "this" @ 0x0x7fff5d659470 {
type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPiNSt9__cxx19986vectorIiSaIiEEEEENSt7__debug6vectorIiS6_EEEE (mutable iterator);
  state = singular;
  references sequence with type `NSt7__debug6vectorIiSaIiEEE' @ 0x0x7fff5d659470
}
Aborted
Run Code Online (Sandbox Code Playgroud)

请理解该程序无论如何都会引发未定义的行为.只是在调试模式下,未定义行为的后果更为显着.


Lig*_*ica 3

迭代器可能引用不同的元素就足以使它们失效。迭代器应该在其有效生命周期内引用相同的元素。

你是对的,在实践中,如果你要取消引用这样的迭代器,你可能不会遇到任何崩溃或鼻恶魔,但这并不意味着它有效。