5

ポインタ ベクトルのメモリを解放するにはどうすればよいですか? コードは次のとおりです。

class A
{
    private:
        int x,y,z;
    public:
        A(param1, param2, param3)
        {
            x=param1;
            y=param2;
            z=param3;
        }
        ~A()
        {
            //prompts an alertbox, warning me about the successful call of the destructor;
        }
};

...
vector<A*> list;
list.push_back(new A(1,2,3));

list.erase(list.begin()+index);//SHOULD delete the object from the memory;
list.clear();

.erase()メモリが解放されず、デストラクタも呼び出されないことがわかりました。すべてのリスト エントリで繰り返し使用しようとしdeleteましたが、1 回の繰り返しでクラッシュします。エラーを回避するために、リスト エントリが既に NULL であるかどうかを既にチェックしています。何か不足していますか?また、私は STL のみを使用する必要があり、Boost は必要ありません。

4

6 に答える 6

8

list.eraseメンバー要素のメモリの割り当てを解除します (存在する場合は、デストラクタを呼び出します)。それは彼らを呼びませんdelete

ブーストshared_ptrは、これを行うための明白な方法です。それを使用したくない場合は、独自のスマート ポインター クラスを作成するか、 をlist呼び出すdelete前に各ポインターを繰り返し呼び出しeraseます。次のようなものでこれをきれいに行うことができます:

void my_delete(A *p)
{
    delete p;
}

...

std::for_each(list.begin(), list.end(), my_delete);
于 2010-09-14T18:06:01.140 に答える
4
for( std::vector<A*>::iterator i = list.begin(), endI = list.end(); i != endI; ++i)
{
   delete *i;
}
list.clear();

または、新しいラムダ関数を使用する

std::for_each( list.begin(), list.end(), []( A* element) { delete element; });
list.clear();
于 2010-09-14T18:07:28.903 に答える
3

eraseベクトル(ポインタ)にあるものだけを消去し、それらが指している可能性のあるものについては何もしません。

ポイントを削除したい場合は、自分で処理する必要があります。

私のアドバイスは、これを自分で処理することを避け、代わりにBoostの使用を検討することですptr_vector

于 2010-09-14T18:08:25.317 に答える
2

破棄されると、STLコンテナはそれに含まれるオブジェクトを破棄します。それらのオブジェクトがポインタである場合、ポインタを破棄します。裸のダムポインタの場合、これはそれらが指すオブジェクトを削除しません。そのため、通常はスマートポインタを使用するのが最適です。スマートポインタは、削除時に参照するオブジェクトを削除します。std::shared_ptrポインタのコピーと特定のオブジェクトへの参照の数を追跡し、最後のポインタがなくなったときにのみオブジェクトを削除します。これは、適切なスマートポインターを探すときに、常に最初の候補として適しています。コンテナは次のように宣言されます。std::vector< std::shared_ptr<A> >

ただし、コンパイラ/ std libには、が付属していない場合がありますstd::shared_ptr。これは、来年一般的に期待される次のC++標準の機能です。ただし、2003年のTR1機能であるが付属してstd::tr1::shared_ptrいる場合があります(他のすべてが失敗した場合、ブーストはありますが、boost_shared_ptrすでにブーストを除外しています)。

STLコンテナで動的に割り当てられたオブジェクトを手動で管理できますが、それは負担であり、エラーが発生しやすくなります。たとえば、returnステートメントまたは例外によって関数が早期に(手動でクリーンアップする前に)戻るのを防ぐ必要があります。また、コンテナーでのコピー操作に注意する必要があります。(そうでない場合、2つのコンテナーに同じオブジェクトを参照するポインターがあり、2回破棄しようとする可能性があります。)
リソースを手動で管理することはPITAであり、エラーが発生しやすいため、回避するのが最善です。

于 2010-09-14T18:08:38.733 に答える
1

投稿したコードは正規のC++ではありません。さらに、eraseは割り当てたオブジェクトを削除せず、ベクターの内容(この場合はポインター)のみを消去します。割り当てた実際のオブジェクトは削除されていません。これがあなたが望むことをする正しい方法です:

#include <vector>
#include <algorithm>

class A
{
    int x,y,z;

public:
    A (int param1, int param2, int param3) :
        x (param1), y (param2), z (param3)
    {
    }
};

struct Deleter
{
    template <typename T>
    void operator () (T *obj) const
    {
        delete obj;
    }
};

int
main ()
{
    std::vector<A*> list;

    list.push_back (new A (1, 2, 3));
    list.push_back (new A (4, 5, 6));
    list.push_back (new A (7, 8, 9));

    std::for_each (list.begin (), list.end (), Deleter ());
    list.clear ();
}

この問題を安全で再利用可能な方法で解決するBoostPtrContainerライブラリもご覧ください。C ++ 0xには、移動可能なセマンティクスをサポートし、STLコンテナおよびアルゴリズムとともに使用してメモリを自動的にクリーンアップできるstd::unique_ptrテンプレートクラスがあります。

于 2010-09-14T18:11:19.250 に答える
0
for(size_t i = 0; i < list.size(); ++i)
{
    リストを削除[i];
}

list.clear();

このようなものを作成してコードがクラッシュした場合は、正確なコードとクラッシュ情報を投稿してください。

于 2010-09-14T18:05:38.893 に答える