#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]