关于STL中map的erase迭代器是否失效的讨论
2015-10-21 10:16
197 查看
近来,在阅读一份开源代码的时候,看到了类似如下的代码:
上述代码乍看之下确实没有什么问题,但细究的话,似乎也不是甚妥当。在使用STL容器的迭代器时,需要考虑的一个问题就是迭代器是否会失效的问题,那么问题来了:
1. 在上述的代码中,id_names调用earse之后,失效的迭代器是否只有to_erase?
2. 在通常的使用中,或者说map的推荐使用中,为避免迭代器失效并且能够正常遍历,推荐使用方式为:id_names.erase(it++);这样的写法(当然在C++11中,由于map的erase接口的返回修改,也可以使用it=id_names.erase(it);),那么对于上述先直接++it;而后再调用id_names.erase(to_erase);这样的写法,会否存在潜在的隐患呢?
遇到上述问题,需要解决的办法,就是得了解map的实现。
map属于关联型容器,其使用的数据结构是红黑树(百度百科、维基百科)。在树的实现实际都是采用指针的,如windows在实现的时候的部分代码段
因此:
1. 在erase的影响只会是被删除的当前的节点失效,不会造成其他的迭代器失效。
2. 上述代码片段中,id_names_t::iterator to_erase = it; ++it; id_names.erase(to_erase);的效果与id_names.erase(it++);等价。
对于迭代器的失效,不同的容器由于底层的数据结构不同,所引发的迭代器失效的情况也不尽相同,因此在使用的过程中需小心谨慎,以免出现迭代器已经失效却还在被使用的情况发生。
typedef std::map<int, std::string> id_names_t; id_names_t id_names; void EraseName(std::string name) { id_names_t::iterator it = id_names.begin(); while(it != id_names.end()) { if(it->second == name) { id_names_t::iterator to_erase = it; ++it; id_names.erase(to_erase); continue; } ++it; } }
上述代码乍看之下确实没有什么问题,但细究的话,似乎也不是甚妥当。在使用STL容器的迭代器时,需要考虑的一个问题就是迭代器是否会失效的问题,那么问题来了:
1. 在上述的代码中,id_names调用earse之后,失效的迭代器是否只有to_erase?
2. 在通常的使用中,或者说map的推荐使用中,为避免迭代器失效并且能够正常遍历,推荐使用方式为:id_names.erase(it++);这样的写法(当然在C++11中,由于map的erase接口的返回修改,也可以使用it=id_names.erase(it);),那么对于上述先直接++it;而后再调用id_names.erase(to_erase);这样的写法,会否存在潜在的隐患呢?
遇到上述问题,需要解决的办法,就是得了解map的实现。
map属于关联型容器,其使用的数据结构是红黑树(百度百科、维基百科)。在树的实现实际都是采用指针的,如windows在实现的时候的部分代码段
if (_Where._Getcont() != this || this->_Isnil(_Where._Mynode())) _DEBUG_ERROR("map/set erase iterator outside range"); _Nodeptr _Erasednode = _Where._Mynode(); // node to erase ++_Where; // save successor iterator for return _Orphan_ptr(*this, _Erasednode);
因此:
1. 在erase的影响只会是被删除的当前的节点失效,不会造成其他的迭代器失效。
2. 上述代码片段中,id_names_t::iterator to_erase = it; ++it; id_names.erase(to_erase);的效果与id_names.erase(it++);等价。
对于迭代器的失效,不同的容器由于底层的数据结构不同,所引发的迭代器失效的情况也不尽相同,因此在使用的过程中需小心谨慎,以免出现迭代器已经失效却还在被使用的情况发生。
相关文章推荐
- Python学习之安装WingIDE并破解
- 提升网站性能开发的10个技巧
- ZooKeeper系列之八:ZooKeeper的简单操作
- jQuery :eq() 选择器
- [架构师]怎么成为一个软件架构师
- svn : Can not Parse lock / entries hashfile错误解决办法
- git branch -D 大写的D 删除分支
- adb remount 失败:remount failed: Operation not permitted问题解决
- Windows平台eclipse连接Mysql解决方案
- nagios使用问题的解决方案
- 解决eclipse的maven项目无法引用到maven库的错误--mac
- SpringMVC4+Spring+Hibernate4整合
- Linux sort命令
- SPAMS稀疏建模工具箱
- SQL总结(四)编辑类
- 选择控制
- 性能测试培训:批量执行Jmeter脚本之ant调用
- Android的屏幕多样性支持
- Linux执行.sh文件时提示No such file or directory该怎么办(三种解决办法)
- iScroll 下 a 标签失效