STL中list的使用(理论)

来源:互联网 发布:木工设计软件手机 编辑:程序博客网 时间:2024/06/18 13:30

问题的引出:一个关于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的值就被修改了。

(完)

原创粉丝点击