【问题标题】:"Vector erase iterator outside range" when trying to erase a previously saved iterator尝试擦除以前保存的迭代器时“向量擦除迭代器超出范围”
【发布时间】:2021-10-15 10:38:43
【问题描述】:

在我的项目中,我正在尝试创建一个向量并保存一个迭代器,该迭代器指向向量的某个元素,稍后我可能想要删除这些元素。与此同时,新元素将被添加到向量中,在添加一些元素后,我想删除从向量中保存的迭代器。

这是我尝试做的:

std::vector<foo> vec;
vec.push_back(foo());
std::vector<foo>::iterator it = vec.begin();

for (int i = 0; i < 10; i++) {
    vec.push_back(foo());
}

vec.erase(it);

但是这样做会出现执行错误,提示“向量擦除迭代器超出范围” 为什么这种方法是错误的?我怎样才能做到正确?

【问题讨论】:

  • 使用索引而不是迭代器。 (顾名思义,迭代器用于迭代。它们不是通用指针。)

标签: c++ iterator stdvector


【解决方案1】:

是的,因为您的代码调用了未定义的行为。

向向量中添加项会使所有迭代器失效,使用失效的迭代器会导致未定义的行为。

原因是向量项有一些保留的内存。当此内存不足以容纳新项目时,将分配新的内存片段并将内容复制到新位置。然后释放旧的内存片段。老迭代器仍然指向刚刚释放的老地方。

在文档中您可以找到:

std::vector<T,Allocator>::push_back - cppreference.com

如果新的size() 大于capacity(),则所有迭代器和引用(包括过去的迭代器)都将失效。否则只有过去的迭代器无效。

要解决问题(并使代码更快),您可以reserve 给定数量的项目所需的空间量。

【讨论】:

    【解决方案2】:

    当大小超过保留容量时,向量迭代器在重新分配时失效。由于您没有执行vec.reserve(10),因此任何push_back 都可能使it 无效。

    请注意,.reserve 本身可能会导致重新分配,因此必须在 it 初始化之前进行。

    【讨论】:

      【解决方案3】:

      这个例子会告诉你会发生什么,你添加到向量中的元素越多,它需要的内存就越多。向量将“增长”并在内存中移动元素。 (这也是为什么调用 reserve 可以加快您的代码,但这是另一回事)

      #include <vector>
      #include <iostream>
      
      struct foo {};
      
      int main()
      {
      
          std::vector<foo> vec;
          vec.push_back(foo());
          std::vector<foo>::iterator it = vec.begin();
      
          auto capacity = vec.capacity();
      
          for (int i = 0; i < 20; i++)
          {
              std::cout << "iteration " << i << ", size = " << vec.size() << ", capacity = " << vec.capacity() << "\n";
              vec.push_back(foo());
              if (capacity != vec.capacity())
              {
                  std::cout << "vector memory has been reallocated, all iterators are no longer valid\n";
                  capacity = vec.capacity();
              }
          }
      
          //vec.erase(it);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-02
        • 2014-06-11
        • 1970-01-01
        • 2018-01-27
        • 2019-01-24
        • 2021-05-08
        相关资源
        最近更新 更多