list/map中安全删除元素
2014-12-17 16:11
155 查看
最近遇到在map中删除元素安全性的问题,于是查了查资料,记录一下。
问题:
It++之后为什么It值由0x00372320变为0xDDDDDDE5而不是指向下一个元素地址?
答案:
看看数据结构就明白了,每一个节点包括数据部分和指针部分,指针指向下一个节点,如果iterator指向当前节点,移除当前元素之后,下一个元素的地址也丢失了,所以It++时找不到下一个元素。
本人刚开始就犯了上面这样的错误,学过数据结构的朋友知道,链表中的每个节点包括两部分,数据部分和指针部分,指针指向下一个节点的地址,当It指向当前节点并对当前节点进行删除操作时,下一节点的地址就丢失了,多么可怕!
正确写法:
上面代码在堆上创建了三个对象,然后将三个对象加入队列,最后将对象erase,那还需不需要delete呢?答案是需要!erase不等同于delete,安全的做法是先delete再erase。
正确代码如下:
*It就是对象指针,不信的话可以打印出*It的值和StudentA的值比较一下,两个值相等。Delete *It2;一定要放在m_MyList.erase(It2);之前,因为m_MyList.erase(It2)执行之后节点被删除,*It2的值就被修改了。
问题的引出:一个关于list::erase()的问题。
写了个小程序试验list在erase一个成员之后iterator 值的变化,程序中注释部分是运行结果显示的数据,代码如下(主要代码):list<CStudent*>::iterator It; for(It = myList.begin(); It != myList.end(); ) { cout<<"It= "<<&(*It)<<endl; // It= 0x00372320 myList.erase(It); cout<<"It= "<<&(*It)<<endl; // It= 0x00372320 It++; cout<<"It= "<<&(*It)<<endl; // It= 0xDDDDDDE5 }
问题:
It++之后为什么It值由0x00372320变为0xDDDDDDE5而不是指向下一个元素地址?
答案:
看看数据结构就明白了,每一个节点包括数据部分和指针部分,指针指向下一个节点,如果iterator指向当前节点,移除当前元素之后,下一个元素的地址也丢失了,所以It++时找不到下一个元素。
移除list中的元素:
List提供了两个函数用于移除成员:erase()和remove(),关于两个函数的用法可以参考MSDN,这里重点讲述用这两个函数时需要注意的问题。注意点一、删除全部元素
错误写法:for(It = myList.begin(); It != myList.end(); It++) { myList.erase(It); }
本人刚开始就犯了上面这样的错误,学过数据结构的朋友知道,链表中的每个节点包括两部分,数据部分和指针部分,指针指向下一个节点的地址,当It指向当前节点并对当前节点进行删除操作时,下一节点的地址就丢失了,多么可怕!
正确写法:
for(It = m_MyList.begin(); It != m_MyList.end();) { list<CStudent*>::iterator It2; It2 = It; It++; m_MyList.erase(It2); }注意,for循环里没有It++。
注意点二、当List成员在堆上创建时
先看下面一段代码:list<CStudent *>myList; CStudent * pStudentA = new CStudent; StudentA->SetInfo(27, "StudentA"); CStudent * pStudentB = new CStudent; StudentB->SetInfo(20, "StudentB"); CStudent * pStudentC = new CStudent; StudentC->SetInfo(24, "StudentC"); myList.push_back(pStudentA); myList.push_back(pStudentB); myList.push_back(pStudentC); list<CStudent*>::iterator It; for(It = myList.begin(); It != myList.end(); ) { list<CStudent*>::iterator It2; It2 = It; It++; m_MyList.erase(It2); }
上面代码在堆上创建了三个对象,然后将三个对象加入队列,最后将对象erase,那还需不需要delete呢?答案是需要!erase不等同于delete,安全的做法是先delete再erase。
正确代码如下:
list<CStudent*>::iterator It; for(It = myList.begin(); It != myList.end(); ) { list<CStudent*>::iterator It2; It2 = It; It++; Delete *It2; // delete每个对象指针 m_MyList.erase(It2); }
*It就是对象指针,不信的话可以打印出*It的值和StudentA的值比较一下,两个值相等。Delete *It2;一定要放在m_MyList.erase(It2);之前,因为m_MyList.erase(It2)执行之后节点被删除,*It2的值就被修改了。
相关文章推荐
- stl的vector,map,list删除元素
- vector, list, map在遍历时删除符合条件的元素
- 遍历List、Map删除元素
- 遍历list或map时删除元素(较巧妙)
- 【Java】集合(List、Set、Map)遍历、删除、比较元素时的小陷阱
- List,Set,Map遍历时删除元素
- vector, list, map在遍历时删除符合条件的元素实现方法
- 如何在遍历list,vector,map时删除符合条件的元素
- vector list map 遍历删除制定元素 防止迭代器失效
- C++ set map list的正确删除元素方法
- vector list map 遍历删除制定元素 防止迭代器失效的实例
- 如何在遍历list,vector,map时删除符合条件的元素
- 编程技巧系列(2)Java 集合(List,Set,Map)遍历时有条件删除特定元素
- Java遍历时删除List、Set、Map中的元素(源码分析)
- vector list map 遍历删除指定元素
- 集合--(List、Set、Map)遍历、删除、比较元素时的小陷阱
- Java如何在List或Map遍历过程中删除元素
- C++/STL用erase删除元素(vector,deque),(list,set,map)
- 如何在遍历list,vector,map时删除符合条件的元素
- 删除map、list集合元素总结