您的位置:首页 > 其它

STL中容器操作的迭代器失效-erase()函数陷阱

2017-08-26 22:04 369 查看
        迭代器失效都是发生在我们在使用容器的过程中要通过迭代器来删除某一个容器节点而导致的迭代器的失效,我们可以从各个容器使用的迭代器以及容器本身的构造结构找到答案,没必要,也不需要去记忆那些陷阱和正确的使用方法。

      每个容器的使用的迭代器类型具体可以到这篇博客去看,下面我们分别看一下每个容器的迭代器失效问题

1.vector 和deque

      这两种容器是支持随机访问迭代器的,可以随机说白了就是可以任意通过各种步长进行向前或者向后来访问容器节点,支持随机访问迭代器也是由于这两种容器本身节点的组成是地址顺序的,因此才可以根据随机的步长来访问各个节点。由于vector和deque在组成上都是顺序的,所以会出现当我们通过迭代器删除当前节点的时候,会导致再次访问后面的节点时候,当前迭代器指向的内存已经不可用了,所以会导致失效。原因在于,顺序结构会在删除本节点时候将后边的节点会依次向前进行移动。尤其是在容器内部实现会在扩容的时候将这段顺序节点转移到其他内存地址。

下面是正确的使用earse()函数进行节点删除的写法:(erase会返回删除节点后面节点的正确地址给迭代器变量)

std::vector< int> Vec;
std::vector< int>::iterator itVec;
for( itVec = Vec.begin(); itVec != Vec.end(); ){
if( *itVec ){
itVec = Vec.erase( itVec);
}
else{
itList++;
}
}
2.list  set 和map
     list 已经set和map这种关联式容器有一个共同的结构组成是他们都是通过不一定连续的节点结构组合起来的,各个节点之间通过保存彼此的地址实现关联,所以他们使用的迭代器类型是双向迭代器。这种迭代器会在删除当前节点时候,只会使当前节点地址失效,而不会使后边节点的地址失效。 因为他们无需进行每个节点中地址重新写入,我们依然可以根据当前删除节点迭代器找到下一个节点的地址。这里的erase()函数也会返回下一个节点的地址。

std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end();) {
if( WillDelete( *itList) ){
itList = List.erase( itList);
}
else{
itList++;
}
}
std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end();){
if( WillDelete( *itList) ){
List.erase( itList++);
}
else{
itList++;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: