2011-04-30 9 views
8

私のC++プログラムでは、newを使用して1つの関数でオブジェクトを作成します。これらのオブジェクトはセットに挿入されます。セットからオブジェクトを削除したいときは、forループでイテレータを使用します。オブジェクトをセットから削除すると、オブジェクトを削除してメモリを解放する必要がありますが、正しいですか?私はdeleteを使ってみましたが、解放されたポインタが割り当てられていないというエラーが表示されます。では、どうやってこれを行うことができますか?セット内のオブジェクトを削除する方法

ここで私は、オブジェクトを作成し、一連の他の関数で

set <myObject> myobjectlist; 
myObject *myobject = new myObject; 
myobjectlist.insert(*myobject); 

に挿入したコード、私はセットからオブジェクトを削除し、そのメモリを解放しようとしている。

for (set<myObject>::iterator i = myobjectlist.begin(); i != myobjectlist.end(); i++) 
if (i->myObjectID == myObjectID) 
{ 
    myobjectlist.erase(*i); 
    delete &i; 
    break; 
} 
は、

「削除」部分がないとうまくいきます。私はオブジェクトのメモリが解放されていないと思ったので、それを追加しました。

答えて

7

セットのerase()メソッドを呼び出すと仮定すると、は、オブジェクトのデストラクタをと呼びます。 erase()オブジェクトの後、すでにdelete dになっています。したがって、手動でdeleteを呼び出す2回目の試みは、ポインタが割り当てられなくなると失敗します。あなたはポインタのリストが必要な場合は、

set <myObject*> myobjectlist;  
    myObject *myobject = new myObject; 
    myobjectlist.insert(myobject); //insert the pointer, not the object 

    for (set<myObject*>::iterator i = myobjectlist.begin(); i != myobjectlist.end(); i++) { 
    if ((*i)->myObjectID == myObjectID) { 
     myobjectlist.erase(i); 
     delete *i; 
     break; 
    } 
    } 
+1

彼のコードスニペットに基づいて、このステートメントは誤解を招きます。彼のセットはオブジェクトを価値によって保存するので、消し去ることは彼が新しいもので割り当てたものではありません。 – hifier

+0

いいえ、彼が参照によって削除しているため、そうではありません。彼のセットには、元のオブジェクトの値のコピーが含まれています。値はセットから消去(および破壊)され、イテレータは削除しようとします。有効なブロックを指していないので、イテレータは機能しません。 –

+1

彼のコードはイテレータを削除しようとしませんが、イテレータの_address_を削除しようとします(新しいアドレスで割り当てられたものへのポインタを保持しているアドレスではありません)。しかし、これはポイントではなく、コードは元のオブジェクトをリークされます。 – hifier

2

はい、作成するオブジェクトを削除する必要があります。しかし、あなたのセットに入っているものは必ずしもあなたが割り当てたものではありません。たとえば、あなたのセットにオブジェクト値(ポインタではなく)が含まれていて、割り当てられたオブジェクトが挿入後にリークしている可能性があります。郵便番号。

編集: それでした。あなたのセットにはポインタは格納されず、割り当てるオブジェクトのコピーが格納されます。あなたの消去ループから削除を削除し、次のようにオブジェクトを挿入します。

set <myObject> myobjectlist; 
myobjectlist.insert(myObject()); 

また、ちょうどあなたのセットがset<myObject*>ことにします。

また、イレーターはイレーターを取ります。これを逆参照する必要はありません。

+0

これらの変更を行うと、forループでコンパイルエラーが発生します。どのように変更する必要がありますか? –

+0

コピーが保存されている場合は、オブジェクトを作成するときに新しいものを使用しないでください。 –

+0

どちらの方法でも、 'erase()'を持つ要素を削除することはできません。 eraseメンバはオブジェクトのデストラクタを呼び出し、deleteは同じことを試みます! –

2

thisはあなたが望むものであることがわかりスマートポインタ。 stdアルゴリズムを使用して正しい項目を見つけ、リストから削除します。

#include <set> 
#include <boost/shared_ptr.hpp> 
#include <boost/bind.hpp> 

using namespace boost; 

typedef boost::shared_ptr<MyObject> t_object; 
std::set<t_object> myObjectList; 
myObjectList.insert(t_object(new MyObject)); 

std::set<t_object>::iterator item = std::find_if(
    myObjectList.begin(), 
    myObjectList.end(), 
    bind(&MyObject::myObjectID, _1)== myObjectID); 
if(item!=myObjectList.end()) 
    myObjectList.erase(item); 
+0

@sean、eraseはイテレータをインクリメントしません。実際、eraseはこのパラメータを値で取るので、イテレータオブジェクトにはまったく影響しません。 – hifier

+0

明確にするために、eraseを呼び出すとセットが変更されるため、イテレータを無効にして、セット内での使用を続けます。ただし、イテレータ自体は変更されず、そのまま消去されたオブジェクトへのポインタを取得するために使用できます。 – hifier

+0

私の混乱はvs2010のerase-set :: eraseの実装に基づいていましたが、それは_Tree :: eraseによって実装されています。これはインクリメントされたイテレータ –

1

のリストを使用します。

参考

は、あなたがこれらのオブジェクトを割り当てるための新しい使用する必要があると仮定し、ここで

関連する問題