'삭제'가 안전합니까? [복제하다
-
23-08-2019 - |
문제
이 질문은 이미 여기에 답이 있습니다.
- 삭제가 허용됩니까? 10 답변
초기 기본 테스트에서는 완벽하게 안전합니다. 그러나 조작을 시도하는 것은 저를 강타했습니다. this
나중에 함수에서 delete
에스 this
런타임 오류가 될 수 있습니다. 이것이 사실이며, 일반적으로 안전합니까? delete this
? 아니면 안전한 경우에만 있습니까?
해결책
delete this
합법적이고 당신이 기대할 수있는 일을합니다. 그것은 당신의 클래스의 소멸자라고 부르고 기본 기억을 해방시킵니다. 후에 delete this
반환, 당신의 this
포인터 가치 ~ 아니다 변경, 이제는 매달려있는 포인터입니다. ~ 아니다 불쾌감을 느끼십시오. 여기에는 클래스의 멤버 변수를 사용한 암시 적 불균칭이 포함됩니다.
일반적으로 참조 카운트 클래스에서 ref-count가 0으로 감소 할 때 DecrementRefCount()
/Release()
/모든 멤버 기능이 호출됩니다 delete this
.
delete this
일반적으로 여러 가지 이유로 매우 나쁜 형태로 간주됩니다. 실수로 회원 변수에 실수로 액세스하기가 쉽습니다 delete this
. 발신자 코드는 객체가 자체 파괴 된 것을 인식하지 못할 수 있습니다.
또한, delete this
코드가 객체 소유권에 대한 대칭 전략이 없을 수도있는 "코드 냄새"입니다. 물체는 자체적으로 할당 할 수 없었습니다 new
, 그래서 전화 delete this
클래스 A가 객체를 할당하고 있지만 클래스 B는 나중에 [self]를 해제하고 있음을 의미합니다.
다른 팁
본질적으로 메소드의 마지막 작업 인 한 "this"를 삭제하는 것이 안전합니다. 실제로 여러 전문 수준 API가 그렇게합니다 (예를 들어 ATL의 CcomoBject 구현 참조).
유일한 위험은 "삭제"를 호출 한 후 다른 멤버 데이터에 액세스하려고 시도하는 것입니다. 이것은 확실히 안전하지 않습니다.
다른 사람들이 이미 언급 한 것처럼 이것은 완벽하게 합법적입니다. 아직 언급되지 않은 추가 이유는 위험합니다. 힙에 물체가 할당되었다고 가정합니다. 참조 계산 구현의 경우 일반적으로 문제가되지는 않지만 보장하기가 어려울 수 있습니다.
그러나 소멸자에서하지 마십시오!
다른 사람들이 언급 한 바와 같이, 이것은 유효한 관용구이지만 안전을 위해서는 객체가 스택에 인스턴스화되지 않도록해야합니다.
이를 수행하는 한 가지 방법은 생성자와 소멸자를 개인화하고 클래스 공장 함수를 통해 객체 생성을 시행하는 것입니다. 클래스 공장은 정적 멤버 기능이거나 친구 기능이 될 수 있습니다. 그런 다음 "삭제 삭제"를 수행하는 객체의 delete () 메소드를 통해 정리를 수행 할 수 있습니다. COM 객체는 기본적으로 기준 수가 0으로 감소 될 때 발생하는 "이 삭제 삭제"로 참조 계산 된 것을 제외하고는 기본적 으로이 방식으로 작동합니다.
예. 완벽하게 괜찮아야합니다. "이것은"는 단지 포인터 일뿐입니다. 모든 포인터는 삭제를 위해 수행됩니다. 객체 삭제 방법에 대한 정보는 힙 레코드에 포함되어 있습니다. 이것이 IunkNown :: Release ()가 일반적으로 COM 객체에서 구현되는 방법입니다.
삭제하면 삭제중인 객체의 서브 클래스가있을 때 문제가 발생할 수 있습니다. 구조가 상단에서 시작되고 삭제가 바닥에서 시작되는 것을 기억하십시오. 따라서 삭제되면 이것은 계층 구조의 중간에 있으면 기본적 으로이 특정 클래스 아래의 모든 객체를 잃었습니다.
삭제는 참조 계산 객체를 구현할 때 매우 편리합니다. 그 예는 COM 클래스입니다.
읽다 비슷한 토론을 위해. 당신의 이해는 그것이 효과가 있고 필요하며 나중에 액세스 할 수 없기 때문에 위험 할 수 있다는 점에서 옳습니다.
법적 예
안전한 아니요
기본 클래스에서 상속하고 기본 클래스 함수에서 삭제 한 경우 파생 클래스 포인터를 사용하면 충돌이 발생합니다. 예 :
class Base
{
virtual void Release()
{
delete this;
}
}
class Derived : public Base
{
void Foo()
{
...
}
}
main()
{
Base *ptrDerived = new Derived();
ptrDerived->release();
ptrDerived->Foo() //Crash
}