仮想関数テーブルへのポインタはクラスのサイズに影響するのに、このポインタはクラスのサイズに影響しないのはなぜですか? this ポインタはどこに配置され、いつメモリが割り当てられますか?
5 に答える
これは暗黙のパラメーターとして渡されるため、オブジェクト内には格納されません。あなたが書くとき:
struct X
{
void f( int i );
};
X x;
x.f( 42 );
次のように考えることができます。
void f( X* const this, int i ); // of course this would be illegal as "this" is a keyword
f( &x, 42 );
したがって、this
ポインタはメソッドが呼び出された場所から来ています。
仮想関数テーブルへのポインターはオブジェクトに格納されますが、実際にはメンバー関数this
の隠しパラメーターです。実際には、これがある場合:
class X
{
void foo(int bar) const;
};
int main()
{
X x;
x.foo(7);
}
次に、コンパイラは暗黙的に次のようなものに変換します (疑似コード):
class X
{
static void foo(const X * const this, int bar);
};
int main()
{
X x;
X::foo(&x, 7);
}
説明のために疑似コードを示しているだけであることに注意してください。概念的にはそのように想像できますが、実際に起こっていることではありません。
「this」ポインターと同様に、vptr はクラスではなくインスタンスに依存します。
this
ポインターは暗黙的にスタックに配置されます (メソッドへの引数のようなものです)。したがって、呼び出すobj->foo()
と、暗黙的に obj がメソッド foo に渡されます。コンパイラは、 を介してその引数にアクセスできるようにしますthis
。
一般に、このポインターをオブジェクト内に格納する必要はありません。それは冗長です (つまり、オブジェクトを手に入れることができれば、そのアドレスは既に利用可能です)。
ただし、vTable は別の話です。オブジェクトがどの vtable を指すかは、コンパイル時に知ることができず、個別の暗黙の引数もありません。これには、オブジェクト自体に専用のスペースが必要です。
どこにもない。ポインタは左辺値ではなく、this
メモリを占有しません。x + y
これは、 の結果がどこにあるのか( wherex
とy
are )を尋ねるようなもの
int
です。実装に応じて、実際に存在する場所は異なります。たとえば、VC++ はレジスタ ECX に保持する傾向があります (ただし、最適化が使用されている場合は異なる場合があります)。Sun CC for Sparc はこれを registeri0
などに配置します。これはクラスのメンバではなく、暗黙的であってもありません。多くのコンパイラはそれを特別に扱いますが、通常の引数とは異なり、左辺値ではありません。