list/map中安全删除元素

悠悠 2022-08-06 03:14 378阅读 0赞

最近遇到在map中删除元素安全性的问题,于是查了查资料,记录一下。

问题的引出:一个关于list::erase()的问题。

  1. 写了个小程序试验listerase一个成员之后iterator 值的变化,程序中注释部分是运行结果显示的数据,代码如下(主要代码):
  2. list<CStudent*>::iterator It;
  3. for(It = myList.begin(); It != myList.end(); )
  4. {
  5. cout<<"It= "<<&(*It)<<endl; // It= 0x00372320
  6. myList.erase(It);
  7. cout<<"It= "<<&(*It)<<endl; // It= 0x00372320
  8. It++;
  9. cout<<"It= "<<&(*It)<<endl; // It= 0xDDDDDDE5
  10. }

问题:
It++之后为什么It值由0x00372320变为0xDDDDDDE5而不是指向下一个元素地址?
答案:
看看数据结构就明白了,每一个节点包括数据部分和指针部分,指针指向下一个节点,如果iterator指向当前节点,移除当前元素之后,下一个元素的地址也丢失了,所以It++时找不到下一个元素。

移除list中的元素:

  1. List提供了两个函数用于移除成员:erase()和remove(),关于两个函数的用法可以参考MSDN,这里重点讲述用这两个函数时需要注意的问题。

注意点一、删除全部元素

错误写法:

  1. for(It = myList.begin(); It != myList.end(); It++)
  2. {
  3. myList.erase(It);
  4. }
  5. 本人刚开始就犯了上面这样的错误,学过数据结构的朋友知道,链表中的每个节点包括两部分,数据部分和指针部分,指针指向下一个节点的地址,当It指向当前节点并对当前节点进行删除操作时,下一节点的地址就丢失了,多么可怕!

正确写法:

  1. for(It = m_MyList.begin(); It != m_MyList.end();)
  2. {
  3. list<CStudent*>::iterator It2;
  4. It2 = It;
  5. It++;
  6. m_MyList.erase(It2);
  7. }

注意,for循环里没有It++。

注意点二、当List成员在堆上创建时

先看下面一段代码:

  1. list<CStudent *>myList;
  2. CStudent * pStudentA = new CStudent;
  3. StudentA->SetInfo(27, "StudentA");
  4. CStudent * pStudentB = new CStudent;
  5. StudentB->SetInfo(20, "StudentB");
  6. CStudent * pStudentC = new CStudent;
  7. StudentC->SetInfo(24, "StudentC");
  8. myList.push_back(pStudentA);
  9. myList.push_back(pStudentB);
  10. myList.push_back(pStudentC);
  11. list<CStudent*>::iterator It;
  12. for(It = myList.begin(); It != myList.end(); )
  13. {
  14. list<CStudent*>::iterator It2;
  15. It2 = It;
  16. It++;
  17. m_MyList.erase(It2);
  18. }
  19. 上面代码在堆上创建了三个对象,然后将三个对象加入队列,最后将对象erase,那还需不需要delete呢?答案是需要!erase不等同于delete,安全的做法是先deleteerase

正确代码如下:

  1. list<CStudent*>::iterator It;
  2. for(It = myList.begin(); It != myList.end(); )
  3. {
  4. list<CStudent*>::iterator It2;
  5. It2 = It;
  6. It++;
  7. Delete *It2; // delete每个对象指针
  8. m_MyList.erase(It2);
  9. }
  10. \*It就是对象指针,不信的话可以打印出\*It的值和StudentA的值比较一下,两个值相等。Delete \*It2;一定要放在m\_MyList.erase(It2);之前,因为m\_MyList.erase(It2)执行之后节点被删除,\*It2的值就被修改了。

发表评论

表情:
评论列表 (有 0 条评论,378人围观)

还没有评论,来说两句吧...

相关阅读

    相关 删除元素

    题目描述 输入一个递增有序的整型数组A有n个元素,删除下标为i的元素,使其仍保持连续有序。注意,有效下标从0开始。 定义如下两个函数分别实现删除元素操作和数组输出操作。

    相关 删除元素

    题目: 输入一个递增有序的整型数组A有n个元素,删除下标为i的元素,使其仍保持连续有序。注意,有效下标从0开始。 定义如下两个函数分别实现删除元素操作和数组输出操作。 vo