为啥在Visual Studio中擦除位置之前矢量的c ++迭代器也无效?
Posted
技术标签:
【中文标题】为啥在Visual Studio中擦除位置之前矢量的c ++迭代器也无效?【英文标题】:Why c++ iterators of vector before erase position are also invalidated in visual studio?为什么在Visual Studio中擦除位置之前矢量的c ++迭代器也无效? 【发布时间】:2019-01-25 15:01:05 【问题描述】:int removeDuplicates(vector<int>& nums)
vector<int>::iterator iter = nums.begin();
vector<int>::iterator test = nums.begin(); //used to test
while (nums.begin() != nums.end())
vector<int>::iterator temp = iter;
vector<int>::iterator temp2 = ++iter;
if (temp2 == nums.end()) break;
if (*temp == *temp2)
iter = nums.erase(temp);
cout << *test << " "; //test here, error happen
return nums.size();
int main()
vector<int> test = 1,1,2,2,4,5,6,6 ;
int result = removeDuplicates(test);
错误消息:"vector iterator not dereferencable!"
我看过一些文章说“擦除位置之前的迭代器保持有效,只有擦除位置之后的迭代器变得无效。”
但是当我尝试使用上面的代码时,我发现擦除位置之前的迭代器也变得无效,我不知道为什么。请帮忙!
【问题讨论】:
向量的内容是什么?您可以尝试创建一个minimal reproducible example 来展示给我们看吗?也请阅读how to ask good questions,以及this question checklist。 如果我没看错,你只会删除第一个元素,所以永远不会有“擦除位置之前的迭代器” 关于可能发生的事情的提示,如果nums[0] == nums[1]
会怎样?然后你删除 nums[0]
并取消引用一个迭代器到(现在删除的元素)nums[0]
。
感谢您的快速回答,您是对的,我明白了。
【参考方案1】:
vector<int>::iterator iter = nums.begin(); vector<int>::iterator test = nums.begin(); vector<int>::iterator temp = iter;
temp
、iter
和 test
指向同一个元素。
iter = nums.erase(temp);
该元素被删除。这会使temp
和test
无效。 iter
但是被重新分配给下一个元素。
cout << *test << " ";
无效的test
被取消。行为未定义。
只要*temp == *temp2
在第一次迭代中为真,就会重现这种情况。在以后的迭代中,iter
和 temp
不再指向第一个元素。
【讨论】:
【参考方案2】:这应该对你有帮助。
int removeDuplicates(std::vector<int>& nums)
for (auto iter = nums.begin(); iter != nums.end(); /* DO NOT INCREMENT */)
if (std::find(iter + 1, nums.end(), *iter) != nums.end())
iter = nums.erase(iter);
else
++iter;
return static_cast<int>(nums.size());
【讨论】:
【参考方案3】:cppreference.com 对vector::erase
说如下:
在擦除点或之后使迭代器和引用无效,包括 end() 迭代器。
因此,在您的示例中,test
和 temp
均使用 nums.begin()
进行初始化。当您擦除 temp
,这无效 temp
。因此,您需要确保 temp
被重新初始化,或者您保留 erased 元素的副本以供以后使用。
那么像这样改变你的代码怎么样:
int removeDuplicates(vector<int>& nums)
vector<int>::iterator iter = nums.begin();
vector<int>::iterator test = nums.begin(); //used to test
while (nums.begin() != nums.end())
vector<int>::iterator temp = iter;
vector<int>::iterator temp2 = ++iter;
size_t dist = std::distance(nums.begin(), temp);
if (temp2 == nums.end()) break;
if (*temp == *temp2)
iter = nums.erase(temp);
test = nums.begin();
test += dist;
cout << *test << " "; //test here, error happen
return nums.size();
【讨论】:
以上是关于为啥在Visual Studio中擦除位置之前矢量的c ++迭代器也无效?的主要内容,如果未能解决你的问题,请参考以下文章