指针容器陷阱
C++ 模板技法基础----《C++ Template》前5章笔记一、问题
在面向对象的编程世界里,多态占有重要地位。而与多态的概念分不开就是指针了。昨天做程序时,我把一堆指针放入了容器,而这些指针都是动态创建(new)的, 在运行过程中一些对象可能会变为失效状态,我就用remove算法剔除掉。但是这样就有问题了:
剔除的只是指针,而非对象。于是那些对象还是活在内存里,只不过现在剔除了通向他们的道路----指针,于是我们找不到它,但它却还占据着我们的地盘。
二、解决方案
1. 首先想到的自然是智能指针。标准库里只有一个auto_ptr,但缺点颇多,尤其是面对容器,它几乎没有了光彩。看下面一个小程序,就知道了:
-
auto_ptr <int> ap1( new int(12) );
-
vector <auto_ptr <int> > V;
-
V.push_back( ap1 ); //呜呼!出错了
-
倘若真的可以在容器里使用起来,也会引起不小的麻烦,主要是由于auto_ptr在复制构造或赋值过程中只允许一个对象上只有一个auto_ptr,这样在一些临时量的传递构造过程中,无疑就损伤了原先的auto_ptr,然后临时量生存期终结,对象就delete掉了。简直难以想象的糟糕!
像Boost, Loki库中都有智能指针,可惜C++新标准库一直都叫,都没有实施,拖延了那么长时间。期待新标准的出台。
2.好象是Effective里的条款:
条款33:提防在指针的容器上使用类似remove的算法
条款中,是这样解决,写一个函数算子(仿函数),功能是delete失效对象,置容器中相应指针为0.:
-
// 对象失效处理,指针置空
-
void delAndNullifyUncertified(Widget*& pWidget)
-
{
-
if (!pWidget->isCertified()) {
-
delete pWidget;
-
pWidget = 0;
-
}
-
}
-
-
// 将所有对象失效的析构掉,并设为空
-
for_each(v.begin(), v.end(),
-
delAndNullifyUncertified);
-
-
// 去掉空指针
-
v.erase(remove(v.begin(), v.end(),
-
static_cast<Widget*>(0)),
-
v.end());
-
三、总结
总之,还是期待新标准,用智能指针方便多了。在使用指针容器的时候,得多留点神。

2008年8月08日 14:54
佩服一下 :)
我是很难找到耐心去适应 STL 化的 C++ 语法,那一群尖括号,感觉像在写 html。
2008年8月10日 09:04
模板这东西很强大,不过唯一的缺憾,就是大多数编译器不支持分离编译,搞得代码文件看起来不如不用模板的代码清晰,一些东西还是分离开来比较好维护