C++ 中的“delete this”?


delete 是一個用於釋放變數儲存空間的運算子。

this 指標是一種可以訪問的指標,但只能在非靜態成員函式內部訪問,它指向呼叫成員函式的物件的地址。

this 指標儲存當前物件的地址,簡單來說,你可以說 this 指標指向類的當前物件。

每當我們透過其物件呼叫成員函式時,編譯器都會秘密地將呼叫該物件的地址作為第一個引數傳遞給成員函式作為 this 指標。

通常,不應將 delete 運算子用於 this 指標。假設,如果使用,則必須考慮以下幾點。

理想情況下,不應將 delete 運算子用於 this 指標。但是,如果使用,則必須考慮以下幾點。

  • delete 運算子僅適用於使用 new 運算子分配的物件(請參閱此帖子)。如果物件是使用 new 建立的,那麼我們可以執行 delete this,否則,行為未定義。

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;
}
  • 一旦執行了 delete this,則在刪除後不應訪問已刪除物件的任何成員。

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;
   }
};

最好的辦法是根本不做 delete this。

在成員函式內部刪除 this 指標是錯誤的,我們永遠不應該這樣做。但是,如果我們這樣做,可能會發生以下情況,

  • 如果呼叫此成員函式的物件是在棧上建立的,那麼刪除 this 指標要麼使應用程式崩潰,要麼會導致未定義的行為。

  • 如果呼叫此成員函式的物件是使用 new 運算子在堆上建立的,那麼刪除 this 指標將銷燬該物件。它不會在那個特定時間使應用程式崩潰,但在之後,如果某些成員函式嘗試透過此物件訪問成員變數,那麼應用程式將崩潰。

示例

#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() 成員函式中刪除了 this 指標,之後呼叫 displayText() 是安全的,因為它沒有訪問任何成員函式。但是呼叫 displayValue() 將使應用程式崩潰,因為它透過懸空指標(即已刪除的 this 指標)訪問成員變數。

更新於: 2019年8月20日

2K+ 瀏覽量

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告