【问题标题】:Error while using vectors iterators' after insert and erase插入和擦除后使用向量迭代器时出错
【发布时间】:2015-07-27 17:53:44
【问题描述】:

我试图在C++ 中使用向量。我正在尝试使用迭代器在指定位置插入一个元素,然后使用迭代器再次删除一些元素。但是在对这两个操作使用相同的迭代器时出现错误。这是我的代码 -

#include <iostream>
#include <vector>
#include <cctype>
using namespace std;
int main()
{
    vector <int> A(10);

    for (int i=0;i<A.size();i++)
    {
        A[i]=i+1;
    }
    vector<int>::iterator p=A.begin();
    p+=2;

    A.insert(p,1,55);

    A.erase(p,p+2);
    for (int i=0;i<A.size();i++)
    {
        cout << A[i] <<"\n";
    }   
    return 0;
}

这给了我以下输出:

*** Error in `./temp': double free or corruption (out): 0x00000000017d4040 ***
55
3
4
5
6
7
8
9
10
Aborted (core dumped)

如果我在A.erase 之前添加以下两行,我会得到正确答案。

p=A.begin();
p+=2;
A.erase(p,p+2);

那么,如果p仍然指向同一个元素,因为它的值没有改变,为什么我需要重新设置p的值。

【问题讨论】:

    标签: c++


    【解决方案1】:

    std::vector 插入/删除后,所有现有的迭代器都将失效并且不应使用(使用它们会导致未定义的行为)

    请记住,改变向量所包含的项目可能会导致内存分配等,因此旧的迭代器可以指向已释放的内存(如指针)

    因此,当您添加行时,您提到并重新初始化迭代器 - 一切正常。但是在insert 之后现有的p 不再有效。

    检查关于“迭代器失效”的段落:http://en.cppreference.com/w/cpp/container/vector/erasehttp://en.cppreference.com/w/cpp/container/vector/insert

    您可以考虑添加对reserve 的调用,以确保insert 上不会发生重新分配,但我认为这样的代码仍然容易出错且难以维护。

    【讨论】:

    • 但是当我先使用erase 然后使用insert 时,它运行良好。例如- vector&lt;int&gt;::iterator p=A.begin(); p+=2; A.erase(p,p+2); A.insert(p,1,3); 这运行良好。
    • 是的,因为向量实现可能不会在擦除时释放内存(并且插入有时必须分配内存)。但仍然 - 这是实现细节,你不应该依赖它。每当你做一些改变向量大小的事情时,所有的迭代器都应该被认为是“坏的”。
    • 使迭代器无效仅仅意味着使用它是未定义的行为——它有时可能会工作,有时会崩溃。此外,从向量中擦除只会使指向或在被擦除元素之后的迭代器无效。指向已擦除元素之前的迭代器仍然有效。
    【解决方案2】:

    根据标准 (n4296 C++14) [23.3.6.5/1] 向量插入操作会使迭代器无效 - 但并非总是如此:

    备注:如果新容量大于旧容量,会导致重新分配。如果没有发生重新分配, 插入点之前的所有迭代器和引用都保持有效。

    用于擦除 [23.3.6.5/3]

    效果:在擦除点或擦除点之后使迭代器和引用无效。

    这些是规则,您认为正确的行为实际上是 UB(未定义行为)——这意味着即使在 99% 的情况下,它也可能看起来有效。这也取决于编译器中的实现。

    【讨论】:

      猜你喜欢
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 2021-07-03
      相关资源
      最近更新 更多