effective stl 第33条:对包含指针的容器使用remove这一类算法时要特别小心
2016-09-27 10:59
417 查看
#include<iostream> #include<vector> #include<algorithm> using namespace std; class Widget { public: Widget(); ~Widget(); bool isCertified() const{};//该Widget是否已被验证过 private: }; Widget::Widget() { } Widget::~Widget() { } int main() { vector<Widget*> v; for (int i = 0; i < 10; i++) { v.push_back(new Widget); } //做了一系列工作之后,假设要剔除那些未被验证通过的对象 v.erase(remove_if(v.begin(), v.end(), notl(mem_fun(&Widget::isCertified)))); return 0; }
删除容器的指针并不能删除该指针指向的对象。
假设在remove_if调用之前V的布局如下:
在调用remove_if之后:
一旦remove_if和erase都返回之后:
这使得资源泄露更加明显,因此:当容器中存放的是指向动态分配的对象的指针的时候,应该避免使用remove和类似的算法(remove_if和unique),很多情况下,你会发现partition是不错的选择。
如果无法避免使用remove,那么在使用erase-remove算法之前,先把那些指向未被验证过的WIdget的指针删除置空,然后清楚该容器中所有的空指针。
#include<iostream> #include<vector> #include<algorithm> using namespace std; class Widget { public: Widget(); ~Widget(); bool isCertified() const{ return false; };//该Widget是否已被验证过 private: }; Widget::Widget() { } Widget::~Widget() { } void delAndNullifyUncertified(Widget*& pWidget) { if (!pWidget->isCertified()) { delete pWidget;//删除该指针,并把它置空 pWidget = 0; } } int main() { vector<Widget*> v; for (int i = 0; i < 10; i++) { v.push_back(new Widget); } //将所有指向未被验证的Widget对象的指针删除并置空 for_each(v.begin(), v.end(), delAndNullifyUncertified); //删除v中的孔指针:必须将0转换为一个指针,这样C++才能正确推断出remove第三个参数的类型 v.erase(remove(v.begin(), v.end(), static_cast<Widget*>(0)), v.end()); return 0; }
当然这种做法的前提是,你不希望该向量中保留任何空指针。如果你希望它保留空指针,可能只好自己写循环来删除那些满足条件的指针。当你删除一个容器并从该容器中删除元素的时候,有一些微妙的细节值得注意。可以看下第9条的内容。
如果容器中存放的不是普通的指针,而是具有引用计数功能的智能指针,那么与remove相关的困难就不存在了,可以直接使用erase-remove习惯用法。
相关文章推荐
- 对包含指针的容器使用remove要特别小心
- 避免在指针的容器上使用类似remove的算法造成的内存泄漏
- 条款33:提防在指针的容器上使用类似remove的算法
- Effective STL 为包含指针的关联容器指定比较类型
- Effective STL 为包含指针的关联容器指定比较类型
- Effective STL 为包含指针的关联容器指定比较类型
- Effective STL 第7条:如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉
- effective stl:如果确实需要删除元素,则需要在remove这一类算法之后调用erase
- effective stl: 第20条,为包含指针的关联容器指定比较类型
- 迭代器失效(1)-小心使用STL容器的erase()
- Effective STL: Item 44:优先使用与泛型算法同名的成员函数
- 一个包含指针数组的排序和使用函数指针来控制排序方式
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 条款20:为指针的关联容器指定比较类型——effective STL
- 指针实现的栈(包含进制转换算法实现,括号匹配算法实现)【8】
- 容器,迭代器,算法使用小例
- Boost.Interprocess使用手册翻译之八:分配器,容器和内存分配算法(Allocators, containers and memory allocation algorithms)
- 如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉
- Effective STL 条款2:小心对“容器无关代码”的幻想(连载)
- objective-C 使用包含函数指针的结构体