为什么在Visual Studio中,擦除位置之前的向量的C ++迭代器也会无效?

时间:2019-01-25 15:01:06

标签: c++ vector iterator invalidation

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!"

我看到一些文章说“擦除位置之前的迭代器保持有效,只有擦除位置之后的迭代器变为无效”。
但是当我尝试上面的代码时,我发现擦除位置也变为无效之前的迭代器,我不知道为什么。请帮忙!

3 个答案:

答案 0 :(得分:0)

 vector<int>::iterator iter = nums.begin();
 vector<int>::iterator test = nums.begin();

 vector<int>::iterator temp = iter;

tempitertest指向同一元素。

 iter = nums.erase(temp);

该元素被删除。这会使temptest无效。 iter但是会​​重新分配给下一个元素。

cout << *test << " ";

无效的test被指示。行为是不确定的。

只要*temp == *temp2在第一次迭代中为true,就会重现这种情况。在以后的迭代中,itertemp不再指向第一个元素。

答案 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.comvector::erase说以下话:

  

在擦除点或擦除点之后使迭代器和引用无效,包括end()迭代器。

因此,在您的示例中,testtemp都使用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();
}