c++ - 为什么 std::vector::insert 使插入点之后的所有迭代器失效

标签 c++ stdvector

insert 插入到 std::vector 时,C++ 标准确保插入点之前的所有迭代器在容量期间保持有效code> 没有用完(参见 [23.2.4.3/1] 或 std::vector iterator invalidation )。

不允许插入点之后的迭代器保持有效的理由是什么(如果容量没有耗尽)?当然,它们随后会指向不同的元素,但是(根据 std::vector 的假定实现)应该仍然可以使用这样的迭代器(例如取消引用它或递增它)。

最佳答案

您似乎将“无效”迭代器视为唯一会在使用时引发崩溃的迭代器,但标准的定义更为广泛。它包括迭代器仍然可以安全地取消引用的可能性,但不再指向它预期指向的元素。 (这是观察到“未定义行为”意味着“你的程序会立即崩溃”;它也可能意味着“你的程序会默默地计算出错误的结果”甚至“什么都没有”在这个实现中会出现明显的错误。")

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';
}

在 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

但是

$ 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

请理解该程序无论哪种方式都会引发未定义的行为。只是未定义行为的后果在 Debug模式下更为显着。

关于c++ - 为什么 std::vector::insert 使插入点之后的所有迭代器失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17898546/

相关文章:

C++简单类声明程序

c++ - push_back() 和 resize(size()+1) 有区别吗

c++ - 将图像数据复制到 cv::mat 的 vector

c++ - 调用删除器时 shared_ptr 是否仍然拥有它的对象?

c++ - const 迭代器的模板参数而不是迭代器

c++ - 如何使用 CMake 2.8 编译 Allegro 4.9.14

c++ - 从 float 组在 Visual C++ 中创建灰度图像

c++ - 合并排序 : Segmentation error Core Dumped

c++ - std::vector 中止问题

c++ - 运算符 [] 错误的矩阵类代理