在C++中,当你使用 std::vector
的 erase
方法删除一个元素后,所有指向删除元素之后元素的迭代器都会失效。因此,如果你删除了一个元素,然后试图使用一个指向被删除元素的迭代器,你可能会遇到未定义行为,包括访问冲突。
以下案例已经测试过
错误例子:
std::vector<int> v = {1, 2, 3, 4, 5};
auto iter = v.begin() + 2; // iter现在指向数字3
v.erase(v.begin() + 1); // 删除数字2
// iter现在指向的内存已经被释放或重新分配,所以它已经失效
std::cout << *iter << std::endl; // 未定义行为,可能会出现访问冲突
为了避免这个问题,你需要在每次删除一个元素后更新你的迭代器。erase
方法返回一个指向被删除元素之后元素的迭代器,你可以使用它来更新你的迭代器:
正确例子1:普通删除
std::vector<int> v = {1, 2, 3, 4, 5};
auto iter = v.begin() + 2; // iter现在指向数字3
iter = v.erase(v.begin() + 1); // 删除数字2,并更新iter
std::cout << *iter << std::endl; // 正常工作,输出3
正确例子2:循环删除
std::vector<int> v = {1, 2, 3, 4, 5};
for (auto iter = v.begin(); iter != v.end(); /* 不在这里更新iter */) {
if (*iter % 2 == 0) {
// 如果iter指向的元素是偶数,删除它,并用返回的迭代器更新iter
iter = v.erase(iter);
} else {
// 否则,只需将iter向前移动一步
++iter;
}
}