C++ 清理 STL 列表/指针向量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/307082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cleaning up an STL list/vector of pointers
提问by twk
What is the shortest chunk of C++ you can come up with to safely clean up a vector or list of pointers? (assuming you have to call delete on the pointers?)
为了安全地清理向量或指针列表,你能想到的最短的 C++ 块是什么?(假设您必须在指针上调用 delete ?)
list<Foo*> foo_list;
I'd rather not use Boost or wrap my pointers with smart pointers.
我宁愿不使用 Boost 或用智能指针包裹我的指针。
回答by Johannes Schaub - litb
For std::list<T*>
use:
对于std::list<T*>
使用:
while(!foo.empty()) delete foo.front(), foo.pop_front();
For std::vector<T*>
use:
对于std::vector<T*>
使用:
while(!bar.empty()) delete bar.back(), bar.pop_back();
Not sure why i took front
instead of back
for std::list
above. I guess it's the feeling that it's faster. But actually both are constant time :). Anyway wrap it into a function and have fun:
不知道为什么我花了front
而不是back
对std::list
以上。我想这是更快的感觉。但实际上两者都是恒定时间:)。无论如何将它包装成一个函数并玩得开心:
template<typename Container>
void delete_them(Container& c) { while(!c.empty()) delete c.back(), c.pop_back(); }
回答by Mr.Ree
Since we are throwing down the gauntlet here... "Shortest chunk of C++"
既然我们要在这里挑战……“最短的 C++ 块”
static bool deleteAll( Foo * theElement ) { delete theElement; return true; }
foo_list . remove_if ( deleteAll );
I think we can trust the folks who came up with STL to have efficient algorithms. Why reinvent the wheel?
我认为我们可以相信提出 STL 的人拥有高效的算法。为什么要重新发明轮子?
回答by Douglas Leeder
for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); ++it)
{
delete *it;
}
foo_list.clear();
回答by Adisak
If you allow C++11, you can do a very short version of Douglas Leeder's answer:
如果你允许 C++11,你可以做一个非常简短的 Douglas Leeder 的回答:
for(auto &it:foo_list) delete it; foo_list.clear();
回答by Mark Ransom
It's really dangerous to rely on code outside of the container to delete your pointers. What happens when the container is destroyed due to a thrown exception, for example?
依靠容器外的代码来删除指针是非常危险的。例如,当容器因抛出异常而被销毁时会发生什么?
I know you said you don't like boost, but please consider the boost pointer containers.
我知道你说过你不喜欢 boost,但请考虑boost 指针容器。
回答by John Dibling
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>());
回答by CB Bailey
I'm not sure that the functor approach wins for brevity here.
为了简洁起见,我不确定函子方法是否会在这里获胜。
for( list<Foo*>::iterator i = foo_list.begin(); i != foo_list.end(); ++i )
delete *i;
I'd usually advise against this, though. Wrapping the pointers in smart pointers or using a specialist pointer container is, in general, going to be more robust. There are lots of ways that items can be removed from a list ( various flavours of erase
, clear
, destruction of the list, assignment via an iterator into the list, etc. ). Can you guarantee to catch them all?
不过,我通常会建议不要这样做。将指针包装在智能指针中或使用专门的指针容器通常会更加健壮。有很多方法可以从列表中删除项目(各种风格的erase
、clear
、列表的销毁、通过迭代器分配到列表中等)。你能保证抓住他们吗?
回答by Linoliumz
The following hack deletes the pointers when your list goes out of scope using RAII or if you call list::clear().
当您的列表使用 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_;
};
Example:
例子:
std::list<Deleter<Foo> > foo_list;
foo_list.push_back(new Foo());
foo_list.clear();
回答by Heero
for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); it++)
{
delete *it;
}
foo_list.clear();
There's a small reason why you would not want to do this - you're effectively iterating over the list twice.
您不想这样做的一个小原因是 - 您有效地对列表进行了两次迭代。
std::list<>::clear is linear in complexity; it removes and destroys one element at a time within a loop.
std::list<>::clear 的复杂度是线性的;它在循环中一次删除和销毁一个元素。
Taking the above into consideration the simplest to read solution in my opinion is:
考虑到上述情况,我认为最简单的阅读解决方案是:
while(!foo_list.empty())
{
delete foo_list.front();
foo_list.pop_front();
}
回答by Greg Rogers
At least for a list, iterating and deleting, then calling clear at the end is a bit inneficient since it involves traversing the list twice, when you really only have to do it once. Here is a little better way:
至少对于一个列表,迭代和删除,然后在最后调用 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);
}
That said, your compiler may be smart enough to loop combine the two anyways, depending on how list::clear is implemented.
也就是说,您的编译器可能足够聪明,可以循环组合这两者,具体取决于 list::clear 的实现方式。