为啥在达到容量后在向量中进行插入时,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
【问题讨论】:
withstd::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<T>
看起来很相似,但它试图成为一个比 T[]
更好的数组,而且开销很小。该目标与您的目标不直接兼容。
幸运的是,STL 设计是模块化的,因此即使您确实编写了自己的容器来执行此操作,您仍然可以重用所有 STL 算法以及与 STL 兼容的算法(例如 boost 中的算法)。
【讨论】:
以上是关于为啥在达到容量后在向量中进行插入时,C++ 不处理迭代器?的主要内容,如果未能解决你的问题,请参考以下文章