実験

公開:2005-04-22 19:33
更新:2020-02-15 04:36
カテゴリ:c++
#include <iostream>
#include "boost/bind.hpp"
#include "boost/function.hpp"
/**
いろいろなタイプで関数呼び出しを行って、どのようなアセンブラソースが出力されるか
目的:
特になし
コンパイル条件:
/EHa /Ox /GX /GR でコンパイルする
**/
// テスト用クラスA
struct A {
A() : _b(10.0f) , _a(10.0f) {};
const float a() {return _a;};
void a(const float v) {_a += v * _b;};
void b(const float v) {_a += v * _b;};
// ファンクタ
void operator()(const float v){_a = v * _b;};
private:
float _a;
float _b;
};
// テスト用クラスB
// Aに処理を委譲する
struct B {
explicit B(A& a) : _A(a){};
void b(const float v) {_A.a(v);};
const float b(){return _A.a();};
private:
float _a;
float _b;
A& _A;
};
// テスト用クラスC
// インターフェース
struct C {
virtual const float a() const = 0;
virtual void a(const float v) = 0;
virtual void b(const float v) = 0;
};
// テスト用クラスD
// インターフェースCを継承
struct D : C
{
D(const float v) : _b(v) , _a(2.5f) {};
const float a() const {return _a;};
void a(const float v){_a += v * _b;};
void b(const float v){_b += v;};
private:
float _a;
float _b;
};
void main()
{
// テスト用(通常)
typedef boost::function<void (const float)> func;
// テスト用2(メンバ関数版)
typedef boost::function<void (A*,const float)> func2;
// 初期設定
A a_;
B b_(a_);
func func_(boost::bind(&A::a,&a_,_1));
func2 func2_;
func2_ = A::b;
func func3_(a_);
C* _p = new D(0.5f);
// 通常のメンバ関数呼び出し
a_.a(20.0f);
// boost::functionによる呼び出し(bind併用)
func_(30.0f);
// boost::functionによる呼び出し(メンバ関数ポインタ)
func2_(&a_,20.0f);
// boost::functionによる呼び出し(ファンクタ)
func3_(30.0f);
// ファンクタ
a_(30.0f);
// 委譲による呼び出し
b_.b(30.0f);
// 仮想関数呼び出し
_p->a(10.1f);
_p->b(3.1f);
// これはどうでもよい
std::cout << a_.a() * b_.b() * _p->a() << std::endl;
}

結果

; 83   :
; 84   :    // 通常のメンバ関数呼び出し
; 85   :    a_.a(20.0f);
000ec d9 44 24 18  fld     DWORD PTR _a_$[esp+80]
; よくわからない...
; 86   :
; 87   :    // boost::functionによる呼び出し(bind併用)
; 88   :    func_(30.0f);
; 普通の関数呼び出しをおこなう。さらにその先の関数で目的の関数を呼び出す
000f0 68 00 00 f0 41   push    1106247680     ; 41f00000H
000f5 d8 0d 00 00 00
00       fmul    DWORD PTR __real@41a00000
000fb 8d 4c 24 2c  lea     ecx, DWORD PTR _func_$[esp+80]
000ff d8 44 24 18  fadd    DWORD PTR _a_$[esp+80]
00103 d9 5c 24 18  fstp    DWORD PTR _a_$[esp+80]
00107 e8 00 00 00 00   call    ??R?$function1@X$CBMV?$allocator@X@std@@@boost@@QBEXM@Z ; boost::function1 >::operator()
; 89   :
; 90   :    // boost::functionによる呼び出し(メンバ関数ポインタ)
; 91   :    func2_(&a_,20.0f);
; 普通の関数呼び出しをおこなう。さらにその先の関数で目的の関数を呼び出す
0010c 68 00 00 a0 41   push    1101004800     ; 41a00000H
00111 8d 54 24 18  lea     edx, DWORD PTR _a_$[esp+80]
00115 52       push    edx
00116 8d 4c 24 24  lea     ecx, DWORD PTR _func2_$[esp+84]
0011a e8 00 00 00 00   call    ??R?$function2@XPAUA@@$CBMV?$allocator@X@std@@@boost@@QBEXPAUA@@M@Z ; boost::function2 >::operator()
; 92   :
; 93   :    // boost::functionによる呼び出し(ファンクタ)
; 94   :    func3_(30.0f);
; 普通の関数呼び出しをおこなう。さらにその先の関数で目的の関数を呼び出す
0011f 68 00 00 f0 41   push    1106247680     ; 41f00000H
00124 8d 4c 24 38  lea     ecx, DWORD PTR _func3_$[esp+80]
00128 e8 00 00 00 00   call    ??R?$function1@X$CBMV?$allocator@X@std@@@boost@@QBEXM@Z ; boost::function1 >::operator()
; 95   :
; 96   :    // ファンクタ
; 97   :    a_(30.0f);
; インライン化されている
0012d d9 44 24 18  fld     DWORD PTR _a_$[esp+80]
00131 d8 0d 00 00 00
00       fmul    DWORD PTR __real@41f00000
; 98   :
; 99   :    // 委譲による呼び出し
; 100  :    b_.b(30.0f);
; 定数畳み込みされている
; 101  :
; 102  :    // 仮想関数呼び出し
; 103  :    _p->a(10.1f);
; 仮想関数テーブルを使用して呼び出されている
00137 68 9a 99 21 41   push    1092721050     ; 4121999aH
0013c 8b ce        mov     ecx, esi
0013e d9 c0        fld     ST(0)
00140 d9 c9        fxch    ST(1)
00142 d8 c1        fadd    ST(0), ST(1)
00144 d9 5c 24 18  fstp    DWORD PTR _a_$[esp+80]
00148 8b 06        mov     eax, DWORD PTR [esi]
0014a dd d8        fstp    ST(0)
0014c ff 10        call    DWORD PTR [eax]
; 104  :    _p->b(3.1f);
0014e 8b 16        mov     edx, DWORD PTR [esi]
00150 68 66 66 46 40   push    1078355558     ; 40466666H
00155 8b ce        mov     ecx, esi
00157 ff 52 08     call    DWORD PTR [edx+8]