Computer >> 컴퓨터 >  >> 프로그램 작성 >> C++

C++에서 이것을 삭제하시겠습니까?

<시간/>

삭제는 변수의 저장 공간을 해제하는 데 사용되는 연산자입니다.

이 포인터는 비정적 멤버 함수 내부에서만 접근할 수 있는 일종의 포인터로, 멤버 함수를 호출한 객체의 주소를 가리킨다.

이 포인터는 현재 개체의 주소를 보유합니다. 간단히 말해서 이 포인터가 클래스의 현재 개체를 가리킨다고 말할 수 있습니다.

객체를 통해 멤버 함수를 호출할 때마다 컴파일러는 해당 객체를 호출한 주소를 멤버 함수의 첫 번째 매개변수로 비밀리에 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()를 호출하면 매달린 포인터를 통해 멤버 변수에 액세스하기 때문에 응용 프로그램이 충돌합니다. 즉, 이 포인터를 삭제했습니다.