【问题标题】:deque insert invalidation of iterators vs. pointers ( references) [duplicate]迭代器与指针(引用)的双端队列插入失效[重复]
【发布时间】:2013-11-13 14:23:26
【问题描述】:

基于来自 cplusplus.com 的引用

如果插入发生在序列的开头或结尾,则与此容器相关的所有迭代器都无效,但指针和引用保持有效,引用它们在调用之前引用的相同元素。

为什么插入到前端或末尾会使迭代器无效,而不是指针和引用?

【问题讨论】:

    标签: c++ stl insert deque push-back


    【解决方案1】:

    基本上,deque 可以被认为是vector<array<T>*>

    换句话说,它由一个小的“索引”向量组成,其中包含指向一系列固定大小数组的指针。当您在双端队列的开头或结尾插入时,它会填充第一个/最后一个数组,然后在必要时添加另一个数组,因此它永远不需要移动 现有 元素。这就是为什么指针/引用不会失效的原因。

    但是,因为这个“索引”存储在类似于向量的东西中,它可能会在调整大小时被复制和重新分配,因此每次将新数组添加到索引时,索引可能会被复制到不同的内存位置。

    迭代器需要对容器有足够的了解才能对其进行迭代。换句话说,仅仅知道它当前指向的特定元素在哪里是不够的,它还需要知道它是哪个数组的一部分,以及索引在哪里,这样它才能找到下一个/上一个数组。

    因此,有可能使“索引”失效的操作也会使迭代器失效,因为虽然它们可能仍指向有效元素,但它们不再能够迭代整个双端队列。

    【讨论】:

      【解决方案2】:

      指针仍然具有单个项目的正确内存地址,但是当你例如:

      1. 获取指向序列开头的迭代器
      2. 在前面插入新项目

      你还有一个指向开头的迭代器吗?在此示例中,您将错过输出中的数字 5:

      #include <deque>
      #include <iostream>
      using namespace std;
      
      int main()
      {
          deque<int> d;
          d.push_back(1);
          d.push_back(2);
          d.push_back(3);
      
          deque<int>::iterator it=d.begin();
      
          d.push_front(5);
      
          for(;it!=d.end();++it)
          {
              cout << *it << endl;
          }
      }
      

      【讨论】:

      • 肯定有其他原因。 std::list::push_front() 不会使std::list::begin() 返回的迭代器无效。
      • 我相信基于编译器供应商的实现。指针可能具有内存地址。但标准不支持。我在 gcc 5.4 上测试过。删除和插入后地址保持不变。但我认为无法保证在未来的版本中会保留该功能。
      猜你喜欢
      • 2015-06-26
      • 2015-12-24
      • 2013-05-21
      • 2010-12-12
      • 2010-10-29
      • 1970-01-01
      • 2013-06-03
      • 2018-08-07
      • 1970-01-01
      相关资源
      最近更新 更多