"Vector erase iterator outside range" 尝试删除之前保存的迭代器时
"Vector erase iterator outside range" when trying to erase a previously saved iterator
在我的项目中,我正在尝试创建一个向量并保存一个迭代器,该迭代器指向我稍后可能想要删除的向量中的某个元素。同时,新元素将添加到向量中,添加一些元素后我想删除我从向量中保存的迭代器。
这是我尝试做的:
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);
但是这样做会出现执行错误,提示“Vector erase iterator outside range”
为什么这种方法是错误的?我怎样才能做对?
当大小超过保留容量时,向量迭代器在重新分配时失效。由于您没有执行 vec.reserve(10)
,任何 push_back 都可能使 it
.
无效
请注意 .reserve
本身会导致重新分配,因此必须在 it
初始化之前发生。
是的,因为您的代码调用了未定义的行为。
向向量添加项会使所有迭代器失效,使用失效的迭代器会导致未定义的行为。
原因是为向量项保留了一些内存。当此内存不足以容纳新项目时,将分配新的内存片段并将内容复制到新位置。然后释放旧的内存片段。旧的迭代器仍然指向刚刚被释放的旧地方。
在文档中您可以找到:
std::vector<T,Allocator>::push_back - cppreference.com
If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.
要解决问题(并使代码更快),您可以 reserve 给定数量的项目 space 所需的数量。
这个例子会告诉你会发生什么,你添加到向量中的元素越多,它需要的内存就越多。向量将“增长”并在内存中移动元素。
(这也是为什么调用 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);
}
在我的项目中,我正在尝试创建一个向量并保存一个迭代器,该迭代器指向我稍后可能想要删除的向量中的某个元素。同时,新元素将添加到向量中,添加一些元素后我想删除我从向量中保存的迭代器。
这是我尝试做的:
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);
但是这样做会出现执行错误,提示“Vector erase iterator outside range” 为什么这种方法是错误的?我怎样才能做对?
当大小超过保留容量时,向量迭代器在重新分配时失效。由于您没有执行 vec.reserve(10)
,任何 push_back 都可能使 it
.
请注意 .reserve
本身会导致重新分配,因此必须在 it
初始化之前发生。
是的,因为您的代码调用了未定义的行为。
向向量添加项会使所有迭代器失效,使用失效的迭代器会导致未定义的行为。
原因是为向量项保留了一些内存。当此内存不足以容纳新项目时,将分配新的内存片段并将内容复制到新位置。然后释放旧的内存片段。旧的迭代器仍然指向刚刚被释放的旧地方。
在文档中您可以找到:
std::vector<T,Allocator>::push_back - cppreference.com
If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.
要解决问题(并使代码更快),您可以 reserve 给定数量的项目 space 所需的数量。
这个例子会告诉你会发生什么,你添加到向量中的元素越多,它需要的内存就越多。向量将“增长”并在内存中移动元素。 (这也是为什么调用 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);
}