注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

C++小知识49——对象指针删除后内部list的处理  

2014-02-20 16:16:58|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

C++小知识49——指针删除后内部list的处理

 

在类中经常会有std::list的成员,那么如果这个类的指针被销毁后,list内部的成员会是什么样子呢?分下面几种情况讨论一下:

一、list内部存储的是指针

二、list内部存储的是普通的变量或者类对象

三、list内部存储的是数组

看下面的例子:

typedef union __UUID

{

         unsigned char ud[16];

         GUID gd;

}UUIDT;

std::list<UUIDT> listuuid;

std::list<std::shared_ptr<UUIDT>> plist;

std::map<int ,std::shared_ptr<UUIDT>> mapTest;

class TestList

{

public:

         std::list<UUIDT> test;

         UUIDT uud;

         int *p;

         char buf[3];

         std::list<unsigned char[10]> listchar;

};

 

void TestMap()

{

         TestList *tl = new TestList();

         UUIDT uuid0;

         uuid0.gd.Data1 = 10;

         uuid0.gd.Data2 = 20;

         uuid0.gd.Data3 = 30;

         memset(uuid0.gd.Data4, 1, 8);

 

     //普通的数组不可以直接插入list,下面的注释部分会引起异常

         //unsigned char cbuf[10];

         //memset(cbuf,32,10);

         //tl->listchar.push_back(cbuf);

         memset(tl->uud.ud, 2, 16);

         char* pc = (char*)uuid0.ud;

        

         UUIDT*pc1 = &uuid0;

         GUID *pc2 = &uuid0.gd;

         tl->p = new int(32);

         tl->test.push_back(uuid0);

         UUIDT* pc0 = &tl->test.front();

         tl->buf[0] = '32';

         tl->buf[1] = '33';

         tl->buf[2] = '36';

         char *pca = tl->buf;

         //tl->test.push_back(2);

         //tl->test.clear();

         delete tl;

         UUIDT *t = new UUIDT();

         t->gd.Data1 = 300;

         delete t;

         std::shared_ptr<UUIDT> pt1 = std::make_shared<UUIDT>();

         std::shared_ptr<UUIDT> pt2 = std::make_shared<UUIDT>();

         mapTest[0] = pt1; pt1->gd.Data1 = 100;

         mapTest[1] = pt2;

         plist.push_back(pt1);

 

         plist.remove(mapTest[0]);

         mapTest.erase(0);

}

Uuid0在压入tllist中后,会复制一个相同的对象到其内部,而不是使用uuid0本身,这个大家都明白,但是在测试的时候儿就可能会犯糊涂,也就是说list中的地址与uuid0栈上的地址完全不一样,所以不要误把后得当成空间地址,而产生错觉。

tl直接销毁后,list会调用自己的析构函数把空间释放掉,当然,如果你提前clear,也会发现有同样的效果,因为在析构函数中,会调用clear这个函数,有兴趣可以看一下库的代码。

这样第二种和第三种就全明白了,只要是对象或数组,对象析构销毁时,会自动的把空间释放掉。这样就余下第一种情况了,看看tlp这个整形指针,你在内存中监视这个地址会发现,tl销毁后,这个地址内的值是不变化的。同样,到了list内部也是这样,如果你逐一删除list内部的内存,那么就会产生内存泄露了。

这里面还有一些使用了智能指针,这样就不用考虑手动删除内存空间了,其实还有一种情况,可以在某些情况下考虑使用weak_ptrlist中进行控制。这样,你也可以不用每次手动去清除list,只要在使用list时提权时失败再删除就可以了。

还有一个要说明的:list 类的元素是节点存储方式,每删除一个元素,同时会回收这个元素所占有的内存空间。其成员函数remove,erase,pop_front,pop_back,clear等都会回收被删除元素的内存空间。至于即使释放内存用 top 查看其内存只增不减的问题,是现代编译器普遍采用的一项内存优化策略所导致的,即进程中被释放的内存并不是真正地交给操作系统,而是仍归本进程使用。遇到下一次本进程分配内存的时候优先考虑这块被释放的内存空间,而不必每次都向操作系统提出分配内存的请求,从而可提高内存分配的效率。

东西简单,但是却很关键。

 

 

 

 

  评论这张
 
阅读(836)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017