c++ map的erase标准做法问题

标准应是这样的:
for (iter = valmap.begin(); iter != valmap.end(); )
{

 if (3 == *iter)  
      valmap.erase(iter++);  //说是传给erase的是iter的一个副本?iter++是下一个有效的迭代器
 else  
      ++iter;  

}

问1:valmap.erase(iter++); 为什么不等价于valmap.erase(iter); iter++;又不等价于呢valmap.erase(++iter);?

问2:不能理解副本的说法,如果
erase(iter)
{

副本=iter;
删除iter的内容;
iter=副本;

}
然后在哪一步执行iter++时,但是iter的内容被删除了会错误把?难道和树结构有关?

/////////////////////////////
如果是
erase(iter)
{

副本=++iter;
删除iter的内容;
iter=副本;

}
这样能说通了,不过此时调用
valmap.erase(iter); //无++
就好了吧?

阅读 5.4k
2 个回答

前缀++和后缀++的区别

让我们先来看一下下面的代码。

#include <stdio.h>
#include <iostream>
using namespace std;

class Test
{
public:
    Test() {data = 0;}
    
    
    Test operator++() //++前置返回新增
    {
        cout << "++前置" << endl;
        this->data++;
        return *this;
    }
    
    Test operator++(int) //后置++返回旧值
    {
        cout << "后置++" << endl;
        Test temp = *this;
        this->data++;
        return temp;
    }
private:
    int data;
};

int main()
{
    Test t;
    ++t; //调用operator++()
    t++; //调用operator++(int)
    return 0;
}

C++中类的++运算符调用的是operator++这个函数,其中带无名int参数的是后置时调用,无参数的是前缀时调用。
调用前缀++运算符时,对象做++的逻辑(具体做什么要看具体的类)然后再返回对象,最后返回的是++操作后的对象。
调用后置++运算符时,对象先保留一份旧值,然后做++逻辑,最后返回对象++操作前的旧值。

valmap.erase(iter++)如何调用

从上面的说明valmap.erase(iter++)的调用是执行了两个函数,先调用iter对象的operator++(int)函数然后再调用valmap.erase()函数,valmap.erase()的参数为iter对象调用operator++(int)的返回值,那么现在就非常清楚了valmap.erase(iter++);先让迭代器iter对象指向map中的下一个元素,然后返回迭代器的旧值,最后再删除旧的迭代器关联的元素。

总结

有了上面两点说明,我们就知道如何回答问题1和问题2了。

问题1

valmap.erase(iter++); 和valmap.erase(iter); iter++;和valmap.erase(++iter);都是不相同的。
valmap.erase(iter++); 的调用顺序:operator++(int)->valmap.erase()。valmap.erase(iter); iter++; 的调用顺序:valmap.erase()->operator++(int)。valmap.erase(++iter); 的调用顺序:operator++()->valmap.erase()。

问题2

问题1理解透彻了,问题2也就不用再多说了。

编程实践中有一条准则:尽量不要在遍历容器过程中删除被遍历的容器内容。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题