清理指针的STL列表/向量

什么是C ++的最短的块,你可以想出安全地清理向量或指针列表? (假设你必须调用指针删除?)

list<Foo*> foo_list; 

我宁愿不使用Boost或用智能指针来包装我的指针。

既然我们在这里抛弃了这个诀窍……“最短的C ++”

 static bool deleteAll( Foo * theElement ) { delete theElement; return true; } foo_list . remove_if ( deleteAll ); 

我想我们可以相信那些提出STL的人有高效的algorithm。 为什么重新发明轮子?

对于std::list<T*>使用:

 while(!foo.empty()) delete foo.front(), foo.pop_front(); 

对于std::vector<T*>使用:

 while(!bar.empty()) delete bar.back(), bar.pop_back(); 

不知道为什么我拿着front而不是back上面的std::list 。 我想这是更快的感觉。 但实际上两者都是恒定的时间:)。 无论如何,把它包装成一个function,玩得开心:

 template<typename Container> void delete_them(Container& c) { while(!c.empty()) delete c.back(), c.pop_back(); } 
 for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); ++it) { delete *it; } foo_list.clear(); 

如果你允许C ++ 11,你可以做一个非常简短的Douglas Leeder的答案:

 for(auto &it:foo_list) delete it; foo_list.clear(); 

依靠容器外的代码来删除指针是非常危险的。 例如,当容器由于抛出的exception而被销毁时会发生什么?

我知道你说你不喜欢升压,但请考虑升压指针容器 。

 template< typename T > struct delete_ptr : public std::unary_function<T,bool> { bool operator()(T*pT) const { delete pT; return true; } }; std::for_each(foo_list.begin(), foo_list.end(), delete_ptr<Foo>()); 

我不确定functor方法在这里简单胜出。

 for( list<Foo*>::iterator i = foo_list.begin(); i != foo_list.end(); ++i ) delete *i; 

不过,我通常会build议这个。 将智能指针中的指针或使用专用指针容器包装起来一般来说会更健壮。 有很多方法可以从列表中删除项目(各种types的eraseclear ,列表销毁,通过迭代器分配到列表等等)。 你能保证把他们全部抓住?

当你的列表使用RAII超出范围,或者你调用list :: clear()时,下面的hack删除指针。

 template <typename T> class Deleter { public: Deleter(T* pointer) : pointer_(pointer) { } Deleter(const Deleter& deleter) { Deleter* d = const_cast<Deleter*>(&deleter); pointer_ = d->pointer_; d->pointer_ = 0; } ~Deleter() { delete pointer_; } T* pointer_; }; 

例:

 std::list<Deleter<Foo> > foo_list; foo_list.push_back(new Foo()); foo_list.clear(); 

至less对于一个列表来说,迭代和删除,然后在最后调用clear会有点不方便,因为它涉及遍历列表两次,当你真的只需要做一次。 这里有一个更好的方法:

 for (list<Foo*>::iterator i = foo_list.begin(), e = foo_list.end(); i != e; ) { list<Foo*>::iterator tmp(i++); delete *tmp; foo_list.erase(tmp); } 

这就是说,你的编译器可能足够聪明,以循环结合这两个反正,取决于如何实现list :: clear。

 for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); it++) { delete *it; } foo_list.clear(); 

有一个小原因,你不想这样做 – 你有效地遍历列表两次。

std :: list <> :: clear在复杂度上是线性的; 它在一个循环内一次删除和破坏一个元素。

考虑到上述考虑,我认为最简单的解决scheme是:

 while(!foo_list.empty()) { delete foo_list.front(); foo_list.pop_front(); } 

实际上,我相信STD库提供了一种以分配器类的formspipe理内存的直接方法

您可以扩展基本分配器的deallocate()方法,以自动删除任何容器的成员。

我认为/这是它打算的东西的types。

由于C ++ 11:

 std::vector<Type*> v; ... std::for_each(v.begin(), v.end(), std::default_delete<Type>()); 

或者,如果您正在编写模板代码,并且希望避免指定具体types:

 std::for_each(v.begin(), v.end(), std::default_delete<std::remove_pointer<decltype(v)::value_type>::type>()); 

其中(自C ++ 14以来)可以缩写为:

 std::for_each(v.begin(), v.end(), std::default_delete<std::remove_pointer_t<decltype(v)::value_type>>()); 
 void remove(Foo* foo) { delete foo; } .... for_each( foo_list.begin(), foo_list.end(), remove ); 
 for (list<Foo*>::const_iterator i = foo_list.begin(), e = foo_list.end(); i != e; ++i) delete *i; foo_list.clear();