2011-06-14 5 views
16

가능한 중복 :
Is it safe to delete this?"이것을 삭제 하시겠습니까?"나쁜 생각입니까?

나는 연결리스트의 노드 역할을하도록 설계 클래스에 약간의 작업을 해왔

, 그리고 내가주는 거라고 생각 클래스 자체의 삭제 기능을 수행하는 관리 클래스와 반대입니다. 그래서 기본적으로는 다음과 같이 진행됩니다

이제
void Class::Delete() { 
    //Some cleanup code before deleting the object 
    delete this; 
} 

내가이 테스트를했는데 그것을 잘 작동하는 것처럼 보이지만 내가 객체가 코드를 실행의 중간에 있었던 과거의 문제를 했어, 삭제 그런 다음 분명히 더 이상 존재하지 않는 객체를 사용하여 프로그램을 추락 시켰습니다.

"delete this"는 함수의 끝에 있으므로 분명히 함수를 빠져 나와 잘 작동하지만 이런 종류의 연습은 나쁜 생각입니까? 내가 조심하지 않으면 이것이 내 얼굴에 날아갈 수 있을까?

+0

이렇게하는 것이 좋지만 이전에 발견 한 것처럼 반드시 안전하다고는 할 수 없습니다. 더 이상 객체와 상호 작용할 수 없습니다. 스레드 객체가 실행되고 스스로 죽는 것은 의미가 있습니다. 아무것도 아닐지도 모른다. – Matt

답변

21

FAQlite 답변 아주 잘 :

만큼 당신이 조심있는 한, 그것은 ( 이 삭제) 자살을 객체에 대한 확인이다. 나는 "주의"를 정의하는 방법을 여기

는 다음과 같습니다

  1. 당신은 확실히 절대적으로 100 % 양수 여야합니다이 객체가 이 아닌 새로운 []에 의해 (새를 통해 할당하거나 배치 새에 의해 않으며, 로컬 것을 스택에 개체가 있거나 다른 개체의 전체 또는 멤버가 아니지만 보통 보통 새 항목).
  2. 회원이 함수가이 개체에서 마지막 멤버 함수가 호출되도록 절대적으로 100 % 확실해야합니다.
  3. 당신은 (데이터 를 다른 멤버 함수를 호출하거나 접촉을 포함하여이 객체의 어떤 부분을 만지지 않는 멤버 함수의 나머지 (후에는이 줄을 삭제)해야 절대적으로 100 % 양수 여야합니다 회원).
  4. 이 줄을 삭제 한 후에 아무도이 포인터 자체에 을 접촉하지 않는다는 사실에 절대적으로 확신해야합니다. 다른 말로하면, 은 그것을 검사하지 말아야하며, 다른 포인터와 비교하고, NULL과 비교하면, 이 출력되고, 전송되고, 으로 무엇이든 할 수 있습니다. 당신이하지 가 가상 소멸자를 할 때이 포인터가 기본 클래스에 포인터입니다

은 물론 일반적인주의 사항 경우에 적용됩니다.

기본적으로 다른 포인터는 delete과 동일한주의를 기울여야합니다. 그러나 명시 적으로 선언 된 포인터와 비교할 때 자살하는 구성원 함수로 문제가 발생할 수있는 영역이 더 많습니다.

+2

내가 궁금한데 .. 왜 # 4? 포인터 등을 인쇄하면 기본 메모리를 전혀 액세스하지 못합니다. – ThiefMaster

+1

호기심 때문에'delete this;'다음에'this'의 값을 읽지 않는 이유는 무엇입니까? 그것은 어떤 상황에서도 평범한 삭제가 될 것이며, 그 후에는 독서가 허용됩니다 (당연히 거의 쓸모가 없습니다). 표준에서 명시 적으로 금지되어 있습니까? 아니면 FAQ가 약간 지나치게 과장 되었습니까? –

+1

"삭제 연산자에 대한 피연산자가 수정 가능한 l 값인 경우 해당 값은 객체가 삭제 된 후에 정의되지 않습니다." - http://msdn.microsoft.com/en-us/library/h6227113.aspx –

1

정의되지 않은 동작을 포함하지 않는 같은 일을하는 간단한 방법이있다 : 하나는 그들 주위 작업 함정 &의 확실하지 않은 경우

void Class::Delete() { 
    //Some cleanup code before deleting the object 
    std::auto_ptr delete_me(this); 
} 
+2

'이것을 삭제합니까? '와 어떻게 다른가요? 나는'auto_ptr'이'delete this'를 제외하고 어떻게 변해가는지 알 수 없으므로 바닐라 구현에 비해 어떤 이점도 없습니다. 내가 틀렸어? – larsmoa

+1

이 질문에 대답하지 않습니다. 나쁜. – Nawaz

+1

이것이 유일한 이유는 난독 화를 추가하는 것입니다. –

5

delete this를 사용하는 것은 좋은 생각이다.

을 호출하면 개체의 소멸자가 호출되고 동적으로 할당 된 메모리가 해제됩니다.

new을 사용하여 개체를 할당하지 않은 경우 Undefined behaviour이됩니다.
delete this 뒤에 개체의 데이터 멤버 또는 가상 함수 중 하나가 액세스되는 경우 다시 동작이 Undefined Behavior이됩니다.

아마도 위의 경우 delete this을 피하는 것이 가장 좋습니다.

+0

이것은 단순히 잘못된 것입니다. 또는 오히려, 그것은'delete'의 모든 사용에 적용됩니다. 'delete this'에 대해서는 특별한 것이 없습니다. –

2

C++에서이를 수행하는 관용적 인 방법은 소멸자 코드에 정리 코드를 넣은 다음 개체를 삭제할 때 자동으로 호출되도록하는 것입니다.

Class::~Class() { 
    do_cleanup(); 
} 

void ManagingClass::deleteNode(Class* instance) { 
    delete instance; //here the destructor gets called and memory gets freed 
} 
+0

이것은 질문과 어떻게 관련이 있습니까? 정리 코드가 소멸자에 있습니다. 문제는 (delete를 통해) 소멸자를 호출하는 사람입니다. –

+0

@James : 질문에 'Class :: Delete'에 정리 코드가 있습니다. 그것은 주석에서 "// 객체를 삭제하기 전의 정리 코드"라고 말합니다. 왜'Delete'가 호출 될 때 클린업 * 만 * 필요하고,'Class' 타입의 객체가 파괴되지 않는지에 대해서는 질문하는 것이 합리적이라고 생각합니다. 물론 좋은 이유가있는 한 괜찮습니다. –

+0

@Steve Jessop 그것은'Delete' 함수가 실제로 무엇인지에 달려 있습니다; 이것은 단지 예일뿐입니다. 실생활에서는'Delete' 대신에'HandleEventX' 나 그와 비슷한 것으로'delete'가 호출 될 유일한 장소가 될 것입니다. 대부분의 시간; 당신은 객체가 파괴 될 때마다 호출되어야하는 모든 코드는 소멸자에 속하며'delete'를 호출하는 함수가 아니라 일반적인 원칙과 관련하여 옳습니다. –

4

실제로는 빈번한 관용구이며 모든 삭제만큼 안전합니다. 모든 삭제와 함께 추가 코드가 개체에 액세스하려고하므로 개체가 동적 할당되었는지 확인해야합니다. 그러나 일반적으로 후자는 문제가 아닙니다. 관용구는 객체의 의미에 따라 결정되는 수명을 갖는 객체에만 관련되며, 이러한 객체는 항상 동적으로 할당됩니다 ( ). 모든 포인터를 찾는 것 역시 개체 일 수 있습니다 (delete this 사용 여부). 일반적으로 옵저버 패턴의 일부 형식은 객체가 존재하지 않을 것이라는 모든 관심있는 당사자에게 알리기 위해 사용됩니다.

+1

+1 좋은 답변입니다. – Nawaz

+0

나는 Nawaz에 동의합니다. (현재의) 맨 위 답변은 다른 질문에 대한 답변입니다. 즉, "언제 이것을 삭제해도 안전합니까?"입니다. 이는 "좋아요, 일정한 규칙을 따르는 한 할 수 있지만 좋은 생각입니다. 아니면 내가 뭔가 다른 일을하고 있다는 것을 의미합니까? "이것은 훨씬 더 흥미로운 질문입니다. – allyourcode

관련 문제