2010-12-18 10 views
9

私はポインタがあるベクトルコンテナを削除する場所が多いので、まずすべてのポインタを削除してからコンテナをクリアする必要があります。毎回反復してポインタを手動で削除するたびに(私はstl :: algorithms for_eachを認識しています)。すべてのコードを回避するために、ポインタを持つすべてのベクターコンテナを削除するためのテンプレートを作成しました。ここまでは順調ですね。テンプレートを使用して任意のコンテナを削除する

ここでは、マップ、コンカレントコンテナなどを含むいくつかのコンテナタイプがあります。すべてが同じ機能を持ち、削除が行われる限りです。私が持っているDeleteContainer(std::vector<T*>& VecIn)の機能は、上記のようにベクトルでしか動かすことができません。すべてのコンテナで動作するように汎用化する方法はありますか?

編集:すべての答えのためのおかげで、私は私は1つ以上を選択することができることを望みます。この質問につまずいた人には、選択されたものだけでなくすべての答えを読んでください。すべてが素晴らしい情報を提供します。

答えて

7

あなたが既に持っている:あなたがこれを行うにはしたくない場合でも、あなたは、あなたがちょうどあなたがこのようにしたいすべてのSTLコンテナのためにそれを呼び出すことができます。この

template<class T> 
void DeleteContainer(typename T::iterator begin, typename T::iterator end) 
{ 
for(;begin!=end;++begin) 
    delete *begin; 
} 

のようなものを作ることができます有効な回答が、ちょうど代替を提供するために、私はあなたがBoost Pointer Containerの使用を検討し、それがメモリ管理を処理させる必要があると考えている:

このライブラリは、したがって、 標準のようなcontaineを提供します(マップの場合、 マップされたオブジェクトはヒープ割り当て またはクローンオブジェクトでなければなりません)。 標準コンテナのそれぞれには、 のオブジェクトの所有権を例外的にとるポインタ コンテナがあります。

3

あなただけT*boost::shared_ptr<T> instedを使用することができますし、DeleteContainerの理由がありません。

std::some_container<int*> s; 
DeleteContainer<std::some_container<int*> > (s.begin(), s.end()); 
+0

これはあまりC++ ishではありません。 Deleterを手動で呼び出すときに、コンテナは例外として安全ではありません。コンテナがスコープから外れると、RAIIが実際に関数を自動的に呼び出すように、abオブジェクトにコンテナをラップする必要があります。 –

+0

他の回答と同じコメントですが、関連するコンテナを別に処理する必要があります。 – Nim

4

ブーストポインタコンテナを使用できます。
ポインタの維持と削除を正しく保持します。

http://www.boost.org/doc/libs/1_38_0/libs/ptr_container/doc/reference.html

{ 
    boost::ptr_vector<int> data; 

    data.push_back(new int(2)); 
    data.push_back(new int(2)); 
    data.push_back(new int(2)); 
} 
// container deleted and all pointers correctly destroyed. 
4
私は2番目に多くの人々とaviseは shared_ptrを使用します

またはポインタのコンテナを高めます。時々、人々は、オブジェクトは、それらが作成された逆の順序で削除することにしたいので、私は代わりにbeginendrbeginrendを使用

​​

:しかし、あなたは

template <typename Iter> 
void delete_pointers(Iter begin, Iter end) 
{ 
    for (; begin != end; ++begin) delete *begin; 
} 

使用を書くことができます。

また

void destroyFoo(Foo* x) { delete x; } 

std::for_each(v.rbegin(), v.rend(), &destroyFoo); 

またはC++ 0xのラムダのを使用を行うことができます。

+0

私が追加するコメントは、 'pair'でdeleteを呼び出すことができないので、関連するコンテナを別々に扱わなければならないということだけです。 – Nim

+0

@ニム:非常に良い点。キーや値をC++マップで簡単に反復することはできません。 "second_iterator"アダプタを記述する必要があります。 –

+0

Will ::演算子はメモリをただ単に削除しますか、それともデストラクタを呼び出しますか?私はここに疑問がある... – Tomek

0

代わりに、ガベージコレクタを使用して完全に削除することをあきらめることです。Boehm-Reiser-Detlefsコレクタを試すことができます。これはLinux(libgc)上で標準であり、多くの複雑なプログラム今すぐ(gccなど)。 RAIIをあきらめることも良い考えです。当時は良いアイデアでしたが、実際にはうまくいきません。多くのリソースは、独立して作成され、その表現とともに順不同で破棄されます。この上

0

私のテイクは次のようになります。ベクトル、両端キューおよびリストでG ++ 4.4.4でテスト

template<class T> 
void Destroy(T *p) 
{ 
    delete p; 
} 

template<template<typename, typename> class C, typename T1, typename T2> 
void Destroy(C<T1 *, T2> &c) 
{               
    std::for_each(c.begin(), c.end(), Destroy<T1>); 
} 

。他のコンテナおよび/または他のSTL実装のために、void Destroy(C < T1 *、T2 > &c)の追加オーバーロードが必要な場合があります。

+0

これはstd :: some_container のケースを処理しません。 some_container がsome_container よりも頻繁に使用されるので、char * caseを処理する方が良いです。 – Jagannath

1

Tomekが提案したように、私たちは削除を扱う同様の解決法を持つことができます。構造体は空き関数よりも優れていました。

struct Delete 
{ 
    public: 
     template<typename T> 
     void operator()(const T* ptr) const 
     { 
      delete ptr; 
     } 
     void operator()(const char* ptr) const 
     { 
      delete[] ptr; 

    } 
}; 

for_each(some_container.begin()、some_container.end()()を削除)。

+0

これは無料の機能よりもなぜ優れていますか? –

関連する問題