50

std::vectorまたはstd::listポインターを安全にクリーンアップするために思いつくことができる C++ の最短のチャンクは何ですか? (ポインタで削除を呼び出す必要があると仮定しますか?)

list<Foo*> foo_list;

Boost を使用したり、ポインターをスマート ポインターでラップしたりしたくありません。

4

15 に答える 15

57

用途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。速くなった感じなのかな。しかし、実際には両方とも一定の時間です:)。とにかくそれを関数にラップして楽しんでください:

template<typename Container>
void delete_them(Container& c) { while(!c.empty()) delete c.back(), c.pop_back(); }
于 2008-11-20T22:50:23.237 に答える
52

ここでガントレットを投げているので... 「C++の最短チャンク」

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

foo_list . remove_if ( deleteAll );

STL を思いついた人々が効率的なアルゴリズムを持っていると信頼できると思います。なぜ車輪を再発明するのですか?

于 2008-11-21T00:06:05.457 に答える
31
for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); ++it)
{
    delete *it;
} 
foo_list.clear();
于 2008-11-20T22:29:59.673 に答える
13

コンテナーの外部のコードに依存してポインターを削除するのは非常に危険です。たとえば、例外がスローされたためにコンテナーが破棄された場合はどうなりますか?

ブーストが嫌いだとおっしゃっていたのは承知していますが、ブースト ポインター コンテナーを検討してください。

于 2008-11-20T23:14:26.247 に答える
10
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>());
于 2008-11-20T22:23:46.567 に答える
5

ここでファンクターのアプローチが簡潔さのために勝つかどうかはわかりません。

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

ただし、通常はこれに反対することをお勧めします。一般に、ポインタをスマート ポインタにラップするか、専用のポインタ コンテナを使用すると、より堅牢になります。リストからアイテムを削除する方法はたくさんあります (さまざまな種類のeraseclear、リストの破棄、イテレータによるリストへの代入など)。それらをすべて捕まえることを保証できますか?

于 2008-11-20T22:30:26.677 に答える
5

次のハックは、RAII を使用してリストが範囲外になったとき、または list::clear() を呼び出したときにポインターを削除します。

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();
于 2012-04-30T11:33:49.770 に答える
4

実際、STDライブラリは、アロケータクラスの形式でメモリを管理する直接的な方法を提供すると思います。

基本的なアロケータのdeallocate()メソッドを拡張して、任意のコンテナのメンバーを自動的に削除できます。

私は/考える/これはそれが意図されているタイプのものです。

于 2010-04-19T20:34:30.303 に答える
4

少なくともリストの場合、繰り返して削除し、最後に clear を呼び出すことは、リストを 2 回トラバースする必要があるため、少し非効率的です。もう少し良い方法は次のとおりです。

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 の実装方法によっては、コンパイラが 2 つをループ結合するほどスマートな場合があります。

于 2008-11-20T23:19:01.323 に答える
0
for (list<Foo*>::const_iterator i = foo_list.begin(), e = foo_list.end(); i != e; ++i)
    delete *i;
foo_list.clear();
于 2008-11-20T22:30:30.670 に答える