this ポインタ
構文
this
|
|||||||||
キーワード this は、メンバ関数が呼ばれたオブジェクトのアドレスを値とする prvalue 式です。 以下の文脈で現れることができます。
クラス X のメンバ関数内における this の型は X* (X へのポインタ) です。 メンバ関数が cv 修飾されている場合は、 this の型は cv X* (同じに cv 修飾された X へのポインタ) です。 コンストラクタおよびデストラクタは cv 修飾できないため、それらの中では this の型は常に X* です (たとえ const オブジェクトを構築または破棄するときでも)。
this キーワードが許される何らかの文脈 (非静的メンバ関数の本体、メンバ初期化子リスト、デフォルトメンバ初期化子) で非静的クラスメンバが使用されたときは、その名前の前に暗黙の this-> が自動的に追加され、メンバアクセス式となります (そのメンバが仮想メンバ関数の場合は、仮想関数呼び出しとなります)。
クラステンプレートでは、 this は依存式であり、別の式を強制的に依存式とするために明示的な this-> が使用されることがあります。
オブジェクト の構築中に、そのオブジェクトまたはそのいずれかの部分オブジェクトの値が、そのコンストラクタの this ポインタから直接または間接的に取得したものでない glvalue を通してアクセスされた場合、そのように取得したオブジェクトまたは部分オブジェクトの値は未規定です。 別の言い方をすると、 this ポインタはコンストラクタ内ではエイリアスできません。
extern struct D d;
struct D {
D(int a) : a(a), b(d.a) {} // 正しくは b(a) または b(this->a)
int a, b;
};
D d = D(1); // b(d.a) が this を通して取得しなかったため、 d.b は未規定です。
オブジェクトが new によって確保されたことをプログラムが保証できる場合は、 delete this; を実行することができますが、これは解放されたオブジェクトへのすべてのポインタ (this ポインタ自身を含みます) を無効にします。 delete this; が戻った後、そのメンバ関数はクラスのメンバを参照することはできず (this の暗黙の逆参照を発生するため)、他のメンバ関数も呼ぶことはできません。 これは、例えば、管理対象オブジェクトへの最後の参照がスコープ外に出るとき、参照カウントをデクリメントする責任を持つ std::shared_ptr の制御ブロックのメンバ関数で、使用されます。
class ref
{
// ...
void incRef() { ++mnRef; }
void decRef() { if (--mnRef == 0) delete this; }
};
例
class T
{
int x;
void foo()
{
x = 6; // this->x = 6; と同じです。
this->x = 5; // this-> の明示的な使用。
}
void foo() const
{
// x = 7; // エラー、 *this は const です。
}
void foo(int x) // 引数 x が同じ名前のメンバを隠蔽します。
{
this->x = x; // 非修飾名 x は引数を参照します。
// 曖昧性解消のために this-> が必要です。
}
int y;
T(int x) : x(x), // メンバ x 初期化するために引数 x を使用します。
y(this->x) // メンバ y を初期化するためにメンバ x を使用します。
{}
T& operator= ( const T& b )
{
x = b.x;
return *this; // オーバーロード演算子の多くは *this を返します。
}
};
class Outer {
int a[sizeof(*this)]; // エラー、メンバ関数の中ではありません。
unsigned int sz = sizeof(*this); // OK、デフォルトメンバ初期化子の中です。
void f() {
int b[sizeof(*this)]; // OK
struct Inner {
int c[sizeof(*this)]; // エラー、 Inner のメンバ関数の中ではありません。
};
}
}