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!"
我看到一些文章说“擦除位置之前的迭代器保持有效,只有擦除位置之后的迭代器变为无效”。
但是当我尝试上面的代码时,我发现擦除位置也变为无效之前的迭代器,我不知道为什么。请帮忙!
答案 0 :(得分:0)
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
在第一次迭代中为true,就会重现这种情况。在以后的迭代中,iter
和temp
不再指向第一个元素。
答案 1 :(得分:0)
这应该对您有帮助。
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());
}
答案 2 :(得分:0)
cppreference.com对vector::erase
说以下话:
在擦除点或擦除点之后使迭代器和引用无效,包括end()迭代器。
因此,在您的示例中,test
和temp
都使用nums.begin()
进行了初始化。当您擦除 temp
时,此无效 temp
。因此,您需要确保temp
被重新初始化,或者保留 edrased 元素的副本以备后用。
那么如何更改您的代码呢?
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();
}