這個指標

所有非靜態成員函式都有一個隱藏引數,一個指向該類例項的指標,名為 this; 此引數以靜默方式插入引數列表的開頭,並由編譯器完全處理。當在成員函式內訪問類的成員時,通過 this 靜默訪問它; 這允許編譯器對所有例項使用單個非靜態成員函式,並允許成員函式以多型方式呼叫其他成員函式。

struct ThisPointer {
    int i;

    ThisPointer(int ii);

    virtual void func();

    int  get_i() const;
    void set_i(int ii);
};
ThisPointer::ThisPointer(int ii) : i(ii) {}
// Compiler rewrites as:
ThisPointer::ThisPointer(int ii) : this->i(ii) {}
// Constructor is responsible for turning allocated memory into 'this'.
// As the constructor is responsible for creating the object, 'this' will not be "fully"
// valid until the instance is fully constructed.

/* virtual */ void ThisPointer::func() {
    if (some_external_condition) {
        set_i(182);
    } else {
        i = 218;
    }
}
// Compiler rewrites as:
/* virtual */ void ThisPointer::func(ThisPointer* this) {
    if (some_external_condition) {
        this->set_i(182);
    } else {
        this->i = 218;
    }
}

int  ThisPointer::get_i() const { return i; }
// Compiler rewrites as:
int  ThisPointer::get_i(const ThisPointer* this) { return this->i; }

void ThisPointer::set_i(int ii) { i = ii; }
// Compiler rewrites as:
void ThisPointer::set_i(ThisPointer* this, int ii) { this->i = ii; }

在建構函式中,this 可以安全地用於(隱式或顯式)訪問已經初始化的任何欄位或父類中的任何欄位; 相反,(隱式或顯式地)訪問尚未初始化的任何欄位或派生類中的任何欄位是不安全的(由於尚未構造派生類,因此其欄位既未初始化也未存在)。在建構函式中通過 this 呼叫虛擬成員函式也是不安全的,因為任何派生類函式都不會被考慮(由於派生類尚未構造,因此其建構函式尚未更新 vtable)。

還要注意,在建構函式中,物件的型別是建構函式構造的型別。即使將物件宣告為派生型別,也是如此。例如,在下面的例子中,ctd_goodctd_badCtorThisBase() 裡面是 CtorThisBase 型別,在 CtorThis() 裡面輸入 CtorThis,即使它們的規範型別是 CtorThisDerived。由於派生的派生類是圍繞基類構建的,所以例項逐漸遍歷類層次結構,直到它成為其預期型別的​​完全構造的例項。

class CtorThisBase {
    short s;

  public:
    CtorThisBase() : s(516) {}
};

class CtorThis : public CtorThisBase {
    int i, j, k;

  public:
    // Good constructor.
    CtorThis() : i(s + 42), j(this->i), k(j) {}

    // Bad constructor.
    CtorThis(int ii) : i(ii), j(this->k), k(b ? 51 : -51) {
        virt_func();
    }

    virtual void virt_func() { i += 2; }
};

class CtorThisDerived : public CtorThis {
    bool b;

  public:
    CtorThisDerived()       : b(true) {}
    CtorThisDerived(int ii) : CtorThis(ii), b(false) {}

    void virt_func() override { k += (2 * i); }
};

// ...

CtorThisDerived ctd_good;
CtorThisDerived ctd_bad(3);

使用這些類和成員函式:

  • 在好的建構函式中,對於 ctd_good
    • CtorThisBase 是在輸入 CtorThis 建構函式時完全構造的。因此,s 在初始化 i 時處於有效狀態,因此可以被訪問。
    • i 在到達 j(this->i) 之前初始化。因此,i 在初始化 j 時處於有效狀態,因此可以被訪問。
    • j 在到達 k(j) 之前初始化。因此,j 在初始化 k 時處於有效狀態,因此可以被訪問。
  • 在錯誤的建構函式中,對於 ctd_bad
    • k 在達到 j(this->k) 後初始化。因此,k 在初始化 j 時處於無效狀態,並且訪問它會導致未定義的行為。
    • CtorThisDerived 直到 CtorThis 構建完成後才構建。因此,b 在初始化 k 時處於無效狀態,並且訪問它會導致未定義的行為。
    • 物件 ctd_bad 仍然是 CtorThis,直到它離開 CtorThis(),並且不會更新為使用 CtorThisDerived 的 vtable 直到 CtorThisDerived()。因此,virt_func() 將呼叫 CtorThis::virt_func(),無論是打算叫那個還是 CtorThisDerived::virt_func()