web-dev-qa-db-ja.com

std :: vector.clear()は各要素の削除(メモリの解放)を行いますか?

次のコードを検討してください。

#include <vector>

void Example()
{
    std::vector<TCHAR*> list;
    TCHAR* pLine = new TCHAR[20];
    list.Push_back(pLine);
    list.clear();    // is delete called here?
    // is delete pLine; necessary?
}

List.clear()は各要素でdeleteを呼び出しますか?つまりlist.clear()の前後にメモリを解放する必要がありますか?

57

いいえ(ハゲポインターの破壊は何もしないので、例で示すように最後に自分で削除する必要があります)。ただし、ブースト(または他のRAIIベースのイディオム)スマートポインターを使用して、Do The Right Thing(auto_ptrは、コピーなどで互換性のない動作をするため、コンテナでは正しく動作しません。) (Benoitが言及しているように、この場合、basic_stringは、ここで本当に探しているものです。)

スマートポインターの落とし穴を理解する必要があると述べたので、暗黙的にメモリー管理を処理して、明示的に行う必要がないようにすると、エラーが発生しにくくなります。

編集:EarwickerとJames Mattaからの強い発言のおかげで、Benoitがはるかに徹底的な答えをもたらした要素を含むように大幅に修正されました。

33
Ruben Bartelink

std :: vectorは、clear()が呼び出されたときに、含まれるすべての要素のデストラクターを呼び出します。特定のケースでは、ポインターは破棄されますが、オブジェクトは残ります。

スマートポインターは正しい方法ですが、注意してください。 auto_ptrはstdコンテナでは使用できません。 boost :: scoped_ptrもできません。 boost :: shared_ptrは使用できますが、オブジェクトへのポインターがないため実際には機能しません。実際には配列を使用しています。したがって、あなたの問題の解決策は boost :: shared_array を使用することです。

しかし、代わりにstd :: basic_stringを使用することをお勧めします。この場合、文字列を操作することの利点を得ながら、メモリ管理に対処する必要はありません。

48
Benoît

これを行う簡単なテンプレート関数を書くことができます:

template <class T>
void deleteInVector(vector<T*>* deleteme) {
    while(!deleteme->empty()) {
        delete deleteme->back();
        deleteme->pop_back();
    }

    delete deleteme;
}

たぶん、ここの何かは悪い習慣ですが、私はそうは思いません。コメントはいつもいいですが、私には大丈夫に見えます。

8

これがそうではないことを伝えることができる1つの方法です-完全に定義されていないクラスで試してください:

#include <vector>
class NotDefined;

void clearVector( std::vector<NotDefined*>& clearme )
{
    clearme.clear();    // is delete called here?
}

このスニペットがコンパイルされる場合、デストラクタが定義されていないため、デストラクタを呼び出すことはできません。

7
tfinniga

いや。ポインタを他の場所で使用していないという保証はないため、それは行われません。ポインター変数ではない場合は、それらを解放します(デストラクターを呼び出すことにより)

5
Mehrdad Afshari

Boost Pointer Container Library を使用することもできます。ここでは特にお勧めしません(ここでも、単一のオブジェクトではなく配列を使用しているため、std::stringがそれを処理します)が、タイトルに記載されている問題を解決する有用であまり知られていないライブラリです。

0
Head Geek