삭제는 변수의 저장 공간을 해제하는 데 사용되는 연산자입니다.
이 포인터는 비정적 멤버 함수 내부에서만 접근할 수 있는 일종의 포인터로, 멤버 함수를 호출한 객체의 주소를 가리킨다.
이 포인터는 현재 개체의 주소를 보유합니다. 간단히 말해서 이 포인터가 클래스의 현재 개체를 가리킨다고 말할 수 있습니다.
객체를 통해 멤버 함수를 호출할 때마다 컴파일러는 해당 객체를 호출한 주소를 멤버 함수의 첫 번째 매개변수로 비밀리에 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()를 호출하면 매달린 포인터를 통해 멤버 변수에 액세스하기 때문에 응용 프로그램이 충돌합니다. 즉, 이 포인터를 삭제했습니다.