为啥在达到容量后在向量中进行插入时,C++ 不处理迭代器?

Posted

技术标签:

【中文标题】为啥在达到容量后在向量中进行插入时,C++ 不处理迭代器?【英文标题】:Why doesn't C++ take care of iterators when insertion is done in a vector after capacity is reached?为什么在达到容量后在向量中进行插入时,C++ 不处理迭代器? 【发布时间】:2012-04-30 17:30:25 【问题描述】:

我编写这个小代码只是为了看看迭代器实际上是如何失效的,并且在达到其容量后不指向向量的更改位置。

这里向量和容量的大小最初都是 5 。之后,我在向量中插入了一些其他元素,并且没有重新初始化我的迭代器以指向myvector.begin()。当再次打印矢量元素时,这会导致在maximum size of vector is : 1073741823 之后的输出中出现49 的垃圾值。

我的问题是,为什么 C++ 在将所有元素复制到新位置后,不会再次将点迭代器指向有效的myvector.begin()? 这也可能导致一些难以调试的行为。我知道一种安全的工作方式是始终在使用迭代器之前重新初始化它。

  #include<iostream>
  #include<vector>
  #include<stdio.h>

  using namespace std;

  int main()
  
    vector<int> myvector;
    vector<int>::iterator it;
    int myarray[]= 100,200,300,400;
    myvector.insert(it,500);
    it=myvector.begin();
    myvector.insert(it,myarray,myarray+4);
    it=myvector.begin();
    for(;it!=myvector.end();++it)
    cout <<*it<<endl;
    cout <<"size of vector is :" << myvector.size() <<"\n"; 
    cout <<"capacity of vector is : " << myvector.capacity()<<"\n";  
    cout <<"maximum size of vector is : " << myvector.max_size()<<"\n"; 
    myvector.push_back(600);
    for(;it!=myvector.end();++it)
    cout <<*it<<endl;
  
  Output of program :-
  100
  200
  300
  400
  500
  size of vector is :5
  capacity of vector is : 5
  maximum size of vector is : 1073741823
  49
  100
  200
  300
  400
  500
  600

【问题讨论】:

with std::vector anything which changes the size invalidates previous iterators @awoodland 他似乎知道这一点,我想他在问为什么会发生这种情况。 每个 STL 容器都对其迭代器的有效性做出一定的保证。了解给定容器的迭代器何时失效是值得的。您当然不想总是重置为新的begin()'以防万一'。请参阅此处以获取有关vector - sgi.com/tech/stl/Vector.html的信息 【参考方案1】:

因为这是不切实际的,而且可能是不可能的。

向量是否应该保留一个所有它的迭代器的列表,并且一旦调用了无效触发方法,它们就会修改所有

【讨论】:

不能分配一个空间来保存 myvector.begin() 的地址,所有迭代器都指向该位置,然后从那里指向 vector 的原始地址或起始位置。并且这个保存向量起始位置的地址被修改为为向量分配了新空间?会有很多开销吗?我不是那个专家所以问它。? @Ritesh 如果您有大量迭代器,这将是很多开销而没有特别的收益。请注意,这不仅仅是开始和结束,也不一定只是其中之一。 @Ritesh - 你总是可以创建一个带有迭代器的容器来做到这一点,但鉴于std::list 存在,它在增长时不会失效,这似乎使它不值得。 @awoodland 我想这是我问题的最佳答案。虽然列表对向量有自己的开销【参考方案2】:

迭代器没有以任何有意义的方式与向量绑定(如果是,它如何实现为指针?)。向量不知道迭代器。不使用无效的迭代器是你的工作。

所以您建议为向量类添加大量复杂性......究竟是什么目的?在我们知道这样做是个坏主意的现实世界中,这如何解决问题?

【讨论】:

【参考方案3】:

大概是因为向量必须跟踪所有迭代器的列表,并在它们变得无效时通知它们。这将引入相当多的开销。 STL 容器的操作都有非常明确的失效规则,程序员只需要遵循它们即可。

请注意,根据标准,您不能依赖向量迭代器在插入或删除后完全有效。在调整大小成为实现细节之前,它仍然对您有用。

【讨论】:

【参考方案4】:

STL 并未尝试实现所有可能的容器。虽然您的容器设计当然是可能的,但它只是不包括在内。 std::vector&lt;T&gt; 看起来很相似,但它试图成为一个比 T[] 更好的数组,而且开销很小。该目标与您的目标不直接兼容。

幸运的是,STL 设计是模块化的,因此即使您确实编写了自己的容器来执行此操作,您仍然可以重用所有 STL 算法以及与 STL 兼容的算法(例如 boost 中的算法)。

【讨论】:

以上是关于为啥在达到容量后在向量中进行插入时,C++ 不处理迭代器?的主要内容,如果未能解决你的问题,请参考以下文章

C++中向量的初始容量

C++ 向量初始容量

在插入向量 C++ 之前验证用户输入

C ++(Windows)向量为啥会出现内存错误?

为啥需要两个范围 for 循环来更改 C++ 中向量的这些元素?

为啥 C++ 标准向量在分配或调整大小时会出现段错误? [关闭]