簡體   English   中英

為什么擦除位置之前向量的 c++ 迭代器在 Visual Studio 中也無效?

[英]Why c++ iterators of vector before erase position are also invalidated in visual studio?

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

我看過一些文章說“擦除位置之前的迭代器保持有效,只有擦除位置之后的迭代器才無效”。
但是當我嘗試使用上面的代碼時,我發現擦除位置之前的迭代器也變得無效,我不知道為什么。 請幫忙!

 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為真,就會重現這種情況。 在以后的迭代中, itertemp不再指向第一個元素。

這應該對你有幫助。

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());
}

cppreference.com關於vector::erase如下:

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

所以在你的例子中, testtemp都用nums.begin()初始化。 當您擦除temp ,這會使temp無效 因此,您需要確保重新初始化temp或保留已擦除元素的副本以備后用。

那么如何像這樣改變你的代碼:

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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM