【发布时间】:2014-05-17 10:51:39
【问题描述】:
我已经阅读了一些关于迭代器失效的帖子,似乎需要向量重新分配的插入会使迭代器失效。向量中间的擦除也不应该导致失效吗?
我对此没有清楚的理解,不知道为什么在调整大小并从开头、中间和结尾删除后使用这些迭代器不会破坏它们:
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
vector<int> v;
v.reserve(10);
for (int i = 0; i < 10; i++)
v.push_back(i);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
cout << endl << "RESIZE" << endl << endl;
for (int i = 10; i < 20; i++)
v.push_back(i);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
cout << endl << "RESIZE 2" << endl << endl;
for (int i = 20; i < 200; i++)
v.push_back(i);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
cout << endl << "REMOVES" << endl << endl;
v.erase(v.begin());
v.pop_back();
v.erase(v.begin() + 17);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
return 0;
}
【问题讨论】:
-
迭代器的有效性取决于容器的类型和操作。例如,对于 vector::erase,检查 cplusplus.com/reference/vector/vector/erase 的迭代器有效性部分
-
@Instinct 我没有看到任何迭代器的重用在这里进行。您能否指出您认为发生这种情况的线路?
-
在您的代码中,您每次迭代容器时都会获取新的迭代器,因此您并没有真正测试您提到的擦除和重新调整大小的情况。当您将 b.begin() 的返回值复制到迭代器类型,然后调用 v.push_back(...) 几次,然后尝试使用迭代器时,就会发生迭代器失效。向量具有逻辑大小和物理大小 s.t.物理 >= 逻辑。
-
向量是用连续内存实现的,所以当 push_back(...) 导致逻辑大小大于当前物理大小时,必须将底层内存复制到更大的连续内存块.迭代器有一个指向这个内存的内部指针,所以当这个“增长”操作发生时,迭代器现在在内部引用一块不再是向量一部分的内存,因此它们是无效的。
-
在初始化迭代器后尝试调用 v.capacity() 并将返回值存储在某个临时位置。 v.capacity() 返回向量中当前分配的元素总数,并且大于或等于 v.size()。现在调用 v.push_back(...) 直到向量的大小超过从存储在临时值中的 capacity() 返回的值。当您将大小增加到超过之前的容量时,向量会增长并且迭代器会失效。
标签: c++ vector stl iterator invalidation