2012-09-16 8 views
6

私のクラスでは、メンバー変数がありますstd::vector<node*> childrenポインタをベクトルのベクトルにpush_backするのはメモリリークですか?

次のクラスメンバー関数はメモリリークを作成しますか?

//adds a child node 
{ 
    node* child = new node("blah","blah","blah"); 
    child->Set_Parent(this); 
    children.push_back(child); //<- Is this ok? 
} 

ベクトルは、ポインタのコピーを作成し、私は同じメモリ、 への2つのポインタを持っているし、元のポインタが右、スコープの外に出ますか?

これは単純明快かもしれませんが、私は私の前提を確認したいと思います。
ありがとう

+1

['std :: shared_ptr'](http://en.cppreference.com/w/cpp/memory/shared_ptr)のようなスマートポインタを調べることをお勧めします。 –

+3

@JoachimPileborg: 'std :: unique_ptr'(http://en.cppreference.com/w/cpp/memory/unique_ptr)を使用することもできます。これは、' std :: vector'が移動セマンティクスをサポートしているためです。 – bitmask

+0

ノードが常に親を持つことになっている場合、ノードはコンストラクタの一部にすることができます。その後、あなたは 'children.push_back(新しいノード(" blah "、" blah "、" blah ")、this);' – dtech

答えて

12

まだ漏れではありません。しかし、vectorが範囲外になった場合、またはerase,pop_backなどの要素をベクターから削除する場合は、最初に削除する要素を除いて、手でリークします。

これを行う正しい方法は、vector<node *>からvector<unique_ptr<node>>に変更することです。あなたのコードは

//adds a child node 
{ 
    node* child = new node("blah","blah","blah"); 
    child->Set_Parent(this); 
    children.push_back(std::unique_ptr<node>(child)); 
} 

に変更するか、またはあなたがブーストを使用することができる場合boost::ptr_vector<node>を使用します。

+0

ええ、私は生のポインタを避けることができますが、私はメモリリークを追跡する習慣を得られません! :) ブーストがそのようなクラスを持っていたか分からなかった!感謝 –

+4

最後の行は単に 'children.emplace_back(child);' –

2

ベクトルのデストラクタを含むクラスが呼び出されたときに子ノードの割り当てを忘れた場合、それは唯一のメモリリークです。

+1

素晴らしい!ありがとうございました。ええ、私のデストラクタはベクトルをループし、各ポインタを削除します。ポインタがまもなく消えるため、nullに設定する理由はありません。 –

1

メモリリークではありません。まだベクトルにポインタがあり、必要に応じてメモリを解放することができます。

1

ベクトルが範囲外になると、デストラクターはポイント先のオブジェクトを破壊しません。それはポインタを破壊します - 何もしません。

あなたのコードはnewでそのオブジェクトを作成しました。あなたのコードはそのオブジェクトを削除する責任があります。あなたがそうしなければ、あなたは漏れがあります。早期に、つまりベクターからポインタを削除する前に、さらに大きな問題が発生する場合は、

-3

childrenがクラスメンバーであると仮定すると、クラスdeconstructorのベクトル内のすべてのアイテムを単純に削除するだけです。

struct Foo{}; 

class Bar 
{ 
public: 
    Bar(){}; 
    ~Bar() 
    { 
     for(vector<Foo*>::iterator it = children.begin(); it != children.end(); ++it) 
     { 
      SAFE_DELETE((*it)); //use your own macro/template or use delete if you don't have one 
      delete (*it); 
      (*it) = NULL; 
     } 
    } 
    vector<Foo*>children; 
} 

Foo* p = new Foo(); 
children.push_back(p); 

あなたはnewなしオブジェクトによってヒープに割り当てられ、この場合には、vector<Foo>childではなく、元のオブジェクトのコピーを作成し、ベクター上のすべてのpush_backが格納されていますが、ポインタを使用しているため、使用している場合コピーが作成されると、長期的な用語オブジェクトを指すポインタは単に格納されます。つまり、後でそれを削除する必要があります。

+0

それは理にかなっています。オブジェクト全体が破棄されるため、nullに設定する必要はないと思います。私はマクロ/テンプレートの目的を理解していません。 –

+1

私はそれを正しくしなかった、あなたはそれを削除するときにNULLへのポインタを設定する必要はないと思う? 'safe_delete'は古くから知られているマクロ/テンプレートであり、ヒープ割り当てされた項目を安全に削除することを目的としています。私はDavid MayhewとScott Meyersの有効/より効果的なC++を読むことをお勧めします。 –

+4

私はdownvoterではないが、これはばかげている。 'SAFE_DELETE'は安全ではありません。 'delete'を呼び出す前にポインタがヌルかどうかチェックするだけです。ヌルポインタの削除には何も問題ありません。そのテストの必要はありません。 'delete'を使う代わりに' SAFE_DELETE'を使う必要はありません。 'SAFE_DELETE'を本当に安全にするために、' delete'を呼び出す前に、非NULLポインターが真に 'new'で割り当てられているかどうかをチェックする必要があります。それはしません。ポインタを削除した後にポインタを 'NULL'に設定する理由もありません。私たちはデストラクタにいます。 –

関連する問題