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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:29:24  来源:igfitidea点击:

Cleaning up an STL list/vector of pointers

c++stl

提问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 frontinstead of backfor std::listabove. 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而不是backstd::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?

不过,我通常会建议不要这样做。将指针包装在智能指针中或使用专门的指针容器通常会更加健壮。有很多方法可以从列表中删除项目(各种风格的eraseclear、列表的销毁、通过迭代器分配到列表中等)。你能保证抓住他们吗?

回答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 的实现方式。