c++(のテンプレート関数)をアセンブリの目で見る
【声明:著作権所有、転載歓迎、商業用途に使用しないでください.連絡ポスト:[email protected]】
テンプレートクラスがデータ型を定義している場合、テンプレート関数は関数を定義します.関数である以上、入力データと出力データがあります.テンプレートクラスとの概念の差は多くなく,テンプレート関数の初心も関数操作に共通の特性を抽出するためであり,タイプの違いと違いを遮蔽している.次の簡単なコードで問題を説明できます.
パラメータタイプがclassタイプなら?やってみましょう.まず基本classを定義します.
257行:テンプレート関数compareを呼び出します.関数アドレスは0 x 401014です.dxはpのアドレス、つまりスタック一時変数のアドレスに注意してください.
演算子>リロードを表示するには、compare関数に従います.
(1)先頭呼び出しcall 0 x 0040103 C関数がリロード演算子関数であり、[ebp-18 h]は、コピーされるのがaデータかbデータかを示す
(2)戻り結果を比較した後、データのコピーを開始する.具体的には0 x 402157を参照.ここで、一時変数[ebp-14 h]と一時変数[ebp-4]の動作は無視できる.
(3)関数が戻る前に,一時変数aとbを解析処理し,コード0 x 402169とコード0 x 402175を参照する.
注意:
(1)テンプレート関数を記述する前に,自分の関数が正しく記述されていることを保証する.
(2)テンプレート関数の優先度が非テンプレート関数より低い
(3)テンプレート関数のタイプは,カスタムタイプであってもよいし,c,c++言語の基本タイプであってもよい.
(4)テンプレート関数の使用は常にクラスの算術演算子と混合して使用し,テクニックに注意する.
(5)テンプレート関数におけるポインタ部分の内容については注意
【予告:次のテンプレートは主に特化テンプレート、デフォルトテンプレートについて説明する】
テンプレートクラスがデータ型を定義している場合、テンプレート関数は関数を定義します.関数である以上、入力データと出力データがあります.テンプレートクラスとの概念の差は多くなく,テンプレート関数の初心も関数操作に共通の特性を抽出するためであり,タイプの違いと違いを遮蔽している.次の簡単なコードで問題を説明できます.
int int_compare(int a, int b)
{
return a > b ? a : b;
}
double double_compare(double a, double b)
{
return a > b ? a : b;
}
の上のコードは、より大きな値をとるコードです.2つの関数の最大の違いは入力データ型と出力データ型の違いですが、このようなデータ型の違いを遮断する方法はありませんか?あります.関数テンプレートです.template <typename type>
type compare(type a, type b)
{
return a > b ? a : b;
}
では、テンプレート関数と一般関数には何の違いもありませんが、関数の上でタイプをtypeに抽象化しているだけですが、テンプレート関数はどのように使用すればいいのでしょうか.246: int i_value = compare(2, 3);
00401458 push 3
0040145A push 2
0040145C call @ILT+10(compare) (0040100f)
00401461 add esp,8
00401464 mov dword ptr [ebp-4],eax
247: double d_value = compare(2.3, 3.1);
00401467 push 4008CCCCh
0040146C push 0CCCCCCCDh
00401471 push 40026666h
00401476 push 66666666h
0040147B call @ILT+5(compare) (0040100a)
00401480 add esp,10h
00401483 fstp qword ptr [ebp-0Ch]
248: }
アセンブリコードは、2つのcompare呼び出しの関数アドレスが一致していないことを示している.ここで、整数のcompareアドレスは0 x 40100 fであり、doubleのアドレスは0 x 040100 aである.これは、コンパイラがコンパイル時に2つのcompare関数を同時に生成してくれることを示しています.したがって,テンプレートクラスの本質は,コンパイラが判断処理を増やしながら,手作業の重複労働を減らすことである.また、テンプレートクラスとは異なり、テンプレート関数は定義関数のパラメータタイプを表示する必要はありません.これは、パラメータから関数のタイプを判断できるためです.パラメータタイプがclassタイプなら?やってみましょう.まず基本classを定義します.
class data
{
int value;
public:
explicit data(int m): value(m) {}
~data() {}
int get_value() { return value;}
int operator > (data& d) {return this->get_value() > d.get_value();}
};
次にcompare関数を呼び出します.256: data m(4), n(2);
0040148D push 4
0040148F lea ecx,[ebp-10h]
00401492 call @ILT+40(data::data) (0040102d)
00401497 mov dword ptr [ebp-4],0
0040149E push 2
004014A0 lea ecx,[ebp-14h]
004014A3 call @ILT+40(data::data) (0040102d)
004014A8 mov byte ptr [ebp-4],1
257: data p = compare(m,n);
004014AC mov eax,dword ptr [ebp-14h]
004014AF push eax
004014B0 mov ecx,dword ptr [ebp-10h]
004014B3 push ecx
004014B4 lea edx,[ebp-18h]
004014B7 push edx
004014B8 call @ILT+15(compare) (00401014)
004014BD add esp,0Ch
258: }
256行:dataは2つの基本変数mとnを構築する257行:テンプレート関数compareを呼び出します.関数アドレスは0 x 401014です.dxはpのアドレス、つまりスタック一時変数のアドレスに注意してください.
演算子>リロードを表示するには、compare関数に従います.
241: return a > b ? a : b;
0040212B lea eax,[ebp+10h]
0040212E push eax
0040212F lea ecx,[ebp+0Ch]
00402132 call @ILT+55(data::operator>) (0040103c)
00402137 test eax,eax
00402139 je compare+53h (00402143)
0040213B lea ecx,[ebp+0Ch]
0040213E mov dword ptr [ebp-18h],ecx
00402141 jmp compare+59h (00402149)
00402143 lea edx,[ebp+10h]
00402146 mov dword ptr [ebp-18h],edx
00402149 mov eax,dword ptr [ebp-18h]
0040214C mov dword ptr [ebp-10h],eax
0040214F mov ecx,dword ptr [ebp-10h]
00402152 mov edx,dword ptr [ecx]
00402154 mov eax,dword ptr [ebp+8]
00402157 mov dword ptr [eax],edx
00402159 mov ecx,dword ptr [ebp-14h]
0040215C or ecx,1
0040215F mov dword ptr [ebp-14h],ecx
00402162 mov byte ptr [ebp-4],1
00402166 lea ecx,[ebp+0Ch]
00402169 call @ILT+25(data::~data) (0040101e)
0040216E mov byte ptr [ebp-4],0
00402172 lea ecx,[ebp+10h]
00402175 call @ILT+25(data::~data) (0040101e)
0040217A mov eax,dword ptr [ebp+8]
compareテンプレート文の下に多くのアセンブリ文が構築されていることがわかりました.いくつかの冗長性があります.簡単に紹介します.(1)先頭呼び出しcall 0 x 0040103 C関数がリロード演算子関数であり、[ebp-18 h]は、コピーされるのがaデータかbデータかを示す
(2)戻り結果を比較した後、データのコピーを開始する.具体的には0 x 402157を参照.ここで、一時変数[ebp-14 h]と一時変数[ebp-4]の動作は無視できる.
(3)関数が戻る前に,一時変数aとbを解析処理し,コード0 x 402169とコード0 x 402175を参照する.
注意:
(1)テンプレート関数を記述する前に,自分の関数が正しく記述されていることを保証する.
(2)テンプレート関数の優先度が非テンプレート関数より低い
(3)テンプレート関数のタイプは,カスタムタイプであってもよいし,c,c++言語の基本タイプであってもよい.
(4)テンプレート関数の使用は常にクラスの算術演算子と混合して使用し,テクニックに注意する.
(5)テンプレート関数におけるポインタ部分の内容については注意
【予告:次のテンプレートは主に特化テンプレート、デフォルトテンプレートについて説明する】