C++ 模板技法基础----《C++ Template》前5章笔记

指针容器陷阱

皮贝贝 posted @ 2008年8月08日 17:45 in 岁月舍利 with tags 指针容器 , 3882 阅读

一、问题

    在面向对象的编程世界里,多态占有重要地位。而与多态的概念分不开就是指针了。昨天做程序时,我把一堆指针放入了容器,而这些指针都是动态创建(new)的, 在运行过程中一些对象可能会变为失效状态,我就用remove算法剔除掉。但是这样就有问题了:

     剔除的只是指针,而非对象。于是那些对象还是活在内存里,只不过现在剔除了通向他们的道路----指针,于是我们找不到它,但它却还占据着我们的地盘。

二、解决方案

    1. 首先想到的自然是智能指针。标准库里只有一个auto_ptr,但缺点颇多,尤其是面对容器,它几乎没有了光彩。看下面一个小程序,就知道了:

 

  1.         auto_ptr <int> ap1( new int(12) );
  2.         vector <auto_ptr <int> > V;
  3.         V.push_back( ap1 );      //呜呼!出错了
  4.  

  倘若真的可以在容器里使用起来,也会引起不小的麻烦,主要是由于auto_ptr在复制构造或赋值过程中只允许一个对象上只有一个auto_ptr,这样在一些临时量的传递构造过程中,无疑就损伤了原先的auto_ptr,然后临时量生存期终结,对象就delete掉了。简直难以想象的糟糕!

  像Boost, Loki库中都有智能指针,可惜C++新标准库一直都叫,都没有实施,拖延了那么长时间。期待新标准的出台。

   2.好象是Effective里的条款:

条款33:提防在指针的容器上使用类似remove的算法

   条款中,是这样解决,写一个函数算子(仿函数),功能是delete失效对象,置容器中相应指针为0.:

 

  1. // 对象失效处理,指针置空
  2. void delAndNullifyUncertified(Widget*& pWidget)  
  3. {                                                 
  4.         if (!pWidget->isCertified()) {     
  5.                 delete pWidget;    
  6.                 pWidget = 0;
  7.         }
  8. }
  9.  
  10. // 将所有对象失效的析构掉,并设为空
  11. for_each(v.begin(), v.end(),           
  12.                         delAndNullifyUncertified);     
  13.  
  14. // 去掉空指针
  15. v.erase(remove(v.begin(), v.end(),                 
  16.                         static_cast<Widget*>(0)),       
  17.                         v.end());                     
  18.  

三、总结

     总之,还是期待新标准,用智能指针方便多了。在使用指针容器的时候,得多留点神。

  • 无匹配
Avatar_small
Li Yanrui 说:
2008年8月08日 22:54

佩服一下 :)

我是很难找到耐心去适应 STL 化的 C++ 语法,那一群尖括号,感觉像在写 html。

Head_small
皮贝贝 说:
2008年8月10日 17:04

模板这东西很强大,不过唯一的缺憾,就是大多数编译器不支持分离编译,搞得代码文件看起来不如不用模板的代码清晰,一些东西还是分离开来比较好维护


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter