삭제는 변수의 저장 공간을 해제하는 데 사용되는 연산자입니다.
이 포인터는 비정적 멤버 함수 내부에서만 접근할 수 있는 일종의 포인터로, 멤버 함수를 호출한 객체의 주소를 가리킨다.
이 포인터는 현재 개체의 주소를 보유합니다. 간단히 말해서 이 포인터가 클래스의 현재 개체를 가리킨다고 말할 수 있습니다.
객체를 통해 멤버 함수를 호출할 때마다 컴파일러는 해당 객체를 호출한 주소를 멤버 함수의 첫 번째 매개변수로 비밀리에 this 포인터로 전달합니다.
일반적으로 이 포인터에는 삭제 연산자를 사용하면 안 됩니다. 만약 사용한다면 다음과 같은 점들을 고려해야 한다고 가정하자.
이상적으로는 이 포인터에 대해 삭제 연산자를 사용하지 않아야 합니다. 다만, 사용하는 경우에는 다음과 같은 점을 고려하여야 한다.
-
delete 연산자는 new 연산자를 사용하여 할당된 객체에 대해서만 작동합니다(이 게시물 참조). new를 사용하여 개체를 만든 경우 이를 삭제할 수 있습니다. 그렇지 않으면 동작이 정의되지 않습니다.
filter_none edit play_arrow brightness_4 class A { public: void fun() { delete this; } }; int main() { /* Following is Valid */ A *ptr = new A; ptr->fun(); ptr = NULL; // make ptr NULL to make sure that things are not accessed using ptr. /* And following is Invalid: Undefined Behavior */ A a; a.fun(); getchar(); return 0; }
-
삭제가 완료되면 삭제된 개체의 구성원은 삭제 후 액세스할 수 없습니다.
filter_none edit play_arrow brightness_4 #include<iostream> using namespace std; class A { int x; public: A() { x = 0;} void fun() { delete this; /* Invalid: Undefined Behavior */ cout<<x; } };
가장 좋은 것은 이것을 전혀 삭제하지 않는 것입니다.
멤버 함수 내에서 이 포인터를 삭제하는 것은 잘못된 것입니다. 절대 그렇게 해서는 안됩니다. 하지만 이렇게 하면 다음과 같은 일이 발생할 수 있습니다.
-
이 멤버 함수가 호출되는 객체가 스택에서 생성되면 이 포인터를 삭제하면 애플리케이션이 충돌하거나 정의되지 않은 동작이 발생합니다.
-
이 멤버 함수가 호출되는 객체가 new 연산자를 사용하여 힙에 생성된 경우 이 포인터를 삭제하면 객체가 파괴됩니다. 특정 시간에 응용 프로그램이 충돌하지 않지만 그 후에 일부 구성원 함수가 이 개체를 통해 구성원 변수에 액세스하려고 하면 응용 프로그램이 충돌합니다.
예시
#include <iostream> class Dummy { int m_value; public: Dummy(int val) : m_value(val) {} void destroy(); void displayValue(); void displayText(); }; void Dummy::destroy() { delete this; } void Dummy::displayValue() { std::cout << this->m_value << std::endl; } void Dummy::displayText() { std::cout << "Not accessing any member function" << std::endl; } int main() { Dummy * dummyPtr = new Dummy(5); dummyPtr->destroy(); dummyPtr->displayText(); return 0; }
destroy() 멤버 함수에서 이 포인터를 삭제한 후 displayText()를 호출하면 멤버 함수에 액세스하지 않기 때문에 안전합니다. 그러나 displayValue()를 호출하면 매달린 포인터를 통해 멤버 변수에 액세스하기 때문에 응용 프로그램이 충돌합니다. 즉, 이 포인터를 삭제했습니다.