迭代器失效

关于迭代器失效的问题,我们先从LeetCode上面的一道题说起。

题目:

Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

示例:

Given nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the new length.

小子给出的函数代码为:

int removeDuplicates(vector<int>& nums) 
{
    if (nums.empty())
    {
        return 0;
    }

  int last = 0;
  int length = 1;

  for (auto i = nums.begin(); i != nums.end(); )
    {
        if ( i == nums.begin())
        {
            last = *i;
            ++i;
            continue;
        }

        if (*i == last)
        {
            i = nums.erase(i);//注意迭代器失效
        }
        else
        {            
            last = *i;
            ++length;
            ++i;
        }
    }
    return length;
}

在上面代码中需要注意的就是注释的那附近。

因为迭代器在删除或者添加元素会使旧迭代器后面的迭代器都失效,迭代器的工作原理是将原容器等操作后结果复制到一个新的容器中。若当前元素被删除,那么该元素的迭代器会失效,如果用户还对当前元素进行自增等操作,这是不允许的。

所以正确的操作是,若当前操作是改变容器的长度等会产生迭代器失效的操作,那么对当前迭代器不能使用自增或其他操作。对于后面的元素,可通过erase()返回的迭代器进行操作。

以上代码若忽略迭代器失效,部分代码为:

if (*i == last)
{
  i = nums.erase(i);
  ++i;//迭代器失效
}
else
{
  ++length;
  last = *i;
}

在《C++ Primer》(中文版)这本书的第315页,也说到了很多容器操作可能导致迭代器失效的一些内容。

以上为个人愚见,欢迎指正。

原文地址:https://www.cnblogs.com/TinyGreen/p/8371113.html