8

C ++のクラスメソッドが呼び出されたときに、暗黙の'this'ポインターが最初の引数なのか、最後の引数なのかを知る必要があります。つまり、スタックに最初にプッシュされるか最後にプッシュされるか。

言い換えれば、呼び出されているクラスメソッドがコンパイラによって次のように取得されるかどうかを尋ねています。

int foo::bar(foo *const this, int arg1, int arg2); 
//or:
int foo::bar(int arg1, int arg2, foo *const this);

したがって、拡張により、そしてさらに重要なことに、G++がこのポインターをそれぞれ最後または最初にプッシュするかどうかにも答えます。グーグルに尋問したが、あまり見つからなかった。

ちなみに、C ++関数が呼び出されると、C関数と同じことをしますか?すなわち:

push ebp
mov ebp, esp

全体として、呼び出されるクラスメソッドは次のようになりますか?

; About to call foo::bar.
push dword 0xDEADBEEF
push dword 0x2BADBABE
push dword 0x2454ABCD ; This one is the this ptr for the example.
; this code example would match up if the this ptr is the first argument.
call _ZN3foo3barEpjj

ありがとう、そして多くの義務があります。

編集:物事を明確にするために、私はGCC / G++4.3を使用しています

4

4 に答える 4

15

これは、コンパイラの呼び出し規約とターゲット アーキテクチャによって異なります。

デフォルトでは、Visual C++ はこれをスタックにプッシュしません。x86 の場合、コンパイラはデフォルトで "thiscall" 呼び出し規約を使用し、これを ecx レジスタに渡します。メンバー関数に __stdcall を指定すると、最初のパラメーターとしてスタックにプッシュされます。

VC++ 上の x64 の場合、最初の 4 つのパラメーターはレジスターで渡されます。これは最初のパラメータで、rcx レジスタに渡されます。

Raymond Chen は、数年前に呼び出し規約に関する連載を行いました。x86およびx64の記事は次のとおりです。

于 2009-08-19T00:02:32.460 に答える
9

これはコンパイラとアーキテクチャによって異なりますが、Linux の G++ 4.1.2 では最適化設定がなくthis、レジスタに渡された最初のパラメータとして扱われます。

class A
{
public:
    void Hello(int, int) {}
};

void Hello(A *a, int, int) {}

int main()
{
    A a;
    Hello(&a, 0, 0);
    a.Hello(0, 0);
    return 0;
}

main() の分解:

movl    $0, 8(%esp)
movl    $0, 4(%esp)
leal    -5(%ebp), %eax
movl    %eax, (%esp)
call    _Z5HelloP1Aii

movl    $0, 8(%esp)
movl    $0, 4(%esp)
leal    -5(%ebp), %eax
movl    %eax, (%esp)
call    _ZN1A5HelloEii
于 2009-08-19T00:08:25.150 に答える
2

C++ 標準 (ANSI ISO IEC 14882 2003) のセクション 9.3.2「The this pointer」を読んだところですが、引数リスト内のどこに発生するかについては何も指定されていないようです。個々のコンパイラ。

「-S」フラグを使用して gcc でコードをコンパイルして、アセンブリ コードを生成し、その動作を確認してください。

于 2009-08-19T00:13:11.087 に答える
1

この種の詳細は、C++ 標準では指定されていません。ただし、gcc のC++ ABI (および C++ ABI に準拠するその他の C++ コンパイラ) をよく読んでください。

于 2009-08-19T00:04:04.377 に答える