关于C++的STL中list的理解

list是C++ stl的一个很普通的容器。这篇文章不会去讨论每种接口的用法,我认为那只是流于表面的应用,网上有很多例子。

先拿一个简单的接口看一下:

void push_back ( const T& x );

它的说明如下

Add element at the end

Adds a new element at the end of the list, right after its current last element. The content of this new element is initialized to a copy of x.

This effectively increases the list size by one.

上面这些话的意思是:将一个元素x加到list的尾部,加入的内容是x的一份拷贝。这句话很重要,我们push_back的只是一个对象的副本。

因此,假如我们需要将对象放在list容器里面去管理,同时我们又会在其他流程里面更新这些对象的信息,那么list内的副本信息时不会受到任何修改的。

这显然不是我们要的结果。因此,我们用list管理对象的时候,最后传入所要管理对象的指针。

 

由此,会引出另外一个问题。我们先看一下另外一个接口:

void pop_front ( );

它的说明如下:

Delete first element

Removes the first element in the list container, effectively reducing the list size by one.

This calls the removed element's destructor.

重点看最后一句话,当这个对象被pop出来后,这个对象的析构函数会被调用。假如我们一开始push_back的是一个对象,那么根据之前的讨论,实际上存入的是该对象的副本,‘

当pop的时候,副本的析构函数会被调用。但是如果我们一开始push_back的是对象的指针呢?那么该对象会不会被析构呢?

答案是不会。原因是,像指针,int,double这种都是基本的数据类型,不是对象,不会被析构。

看一段代码吧:

 

class TEST
{
public:
    TEST()
    {
        cout << "constructor" << endl;
        return;
    }
    ~TEST()
    {
        cout << "deconstruction" << endl;
    }

};


void func(void)
{
    TEST *test = new TEST();
    std::list<TEST*> testList;
    testList.push_back(test);
    testList.pop_front();
   return; } void gunc(void) { TEST test; std::list<TEST> testList; testList.push_back(test); test = testList.front(); testList.pop_front(); }



 

#include<iostream>
#include <list>
using namespace std;
int main(int argc, char**argv)
{
	func();
        cout<<"--------分割线---------"<<endl;
	gunc();
	return 0;
}

分析:

func内,我们new了一块动态内存,并将该指针放入了list里面,然后我们又把它pop出来,但是整个函数执行完成后,都没有调用析构函数,这就造成了内存泄露。

gunc内,我们生成了一个局部对象test,并将对象push进了list内,根据前面的讨论我们知道实际上push进去的是test的副本,因此pop的时候调用的

析构函数,实际上是test副本的析构函数,当结束当前调用栈的时候,局部变量test的析构函数被自动调用,因此可以看到两次析构的打印。

 

posted @ 2017-08-17 02:18  24k的帅哥  阅读(314)  评论(0编辑  收藏  举报