2011-04-30 6 views
8

내 C++ 프로그램에서 new를 사용하여 하나의 함수로 개체를 만듭니다. 이러한 개체는 집합에 삽입됩니다. 집합에서 객체를 제거하려면 for-loop에서 반복자를 사용합니다. 집합에서 개체를 제거 할 때 개체를 삭제하여 메모리를 확보해야합니다. 맞습니까? 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를 호출하려는 두 번째 시도는 포인터가 더 이상 할당되지 않아 실패합니다. 당신은 포인터의 목록을해야하는 경우,

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

그의 코드는 반복자를 지우려고 시도하지 않고 iterator의 _address_를 삭제하려고 시도합니다 (새 주소로 할당 된 포인터에 대한 포인터를 보유하고 있지 않은 유효한 주소 임). 그러나 이것은 요점이 아니며, 코드는 원래 객체를 누설합니다. – hifier

2

예, 생성 한 개체를 삭제해야합니다. 그러나, 당신의 세트에있는 것이 반드시 당신이 할당 한 것만은 아닙니다. 예를 들어, 세트에 포인터가 아닌 오브젝트 값이 들어 있고 삽입 된 오브젝트가 누락 된 것일 수 있습니다. 우편 번호.

편집 : 그게 전부입니다. 당신의 세트는 포인터를 저장하지 않고, 할당하고있는 객체의 복사본을 저장합니다. 이 같은 객체를 당신의 삭제 루프에서 삭제를 제거하고 삽입 :

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

을 다른 방법으로, 당신의 세트 set<myObject*>이 될 수 있도록.

또한 지우기에는 반복기가 필요하므로이를 역 참조 할 필요가 없습니다.

+0

이러한 변경을하면 for-loop에서 컴파일 오류가 발생합니다. 어떻게 변경해야합니까? –

+0

복사본을 저장하는 경우 개체를 만들 때 new를 사용하지 않는 것이 좋습니다. –

+0

어느 쪽이든'erase()'를 가진 원소를 지울 수 없다. d. erase 멤버는 객체의 소멸자를 호출하고 delete는 동일한 작업을 시도합니다! –

2

this 당신이 원하는 참조 스마트 포인터. 표준 알고리즘을 사용하여 올바른 항목을 찾아 목록에서 지 웁니다.

#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 구현을 기반으로했으나 void를 반환하지만 _Tree :: erase를 통해 구현됩니다.이 반복자는 증가 된 반복자를 반환합니다 –

1

의 목록을 사용

참고로

, 당신은 이러한 개체를 할당하는 새로운 사용할 필요가 가정, 여기

관련 문제