インライン関数は、呼び出された場所で置き換えられるか、通常の関数として動作することを知っています。
しかし、インライン関数をインラインとして扱うかどうかの判断はコンパイル時に行われるので、インライン関数が実際に呼び出された場所で実際に置き換えられているかどうかはどうすればわかりますか?
実行時にプログラムで行うことはできません。
そして問題の真実は次のとおりです:知る必要はありません
コンパイラはinline
とマークされていないinline
関数を選択するか、明示的にinline
とマークされた関数を無視できます。これは完全に望みです(read wisdom)コンパイラの&あなたはコンパイラがその仕事を慎重に行うことを信頼するべきです。主流のコンパイラのほとんどは、うまく機能します。
あなたの質問が純粋に学問的な観点からのものである場合、利用可能なオプションがいくつかあります:
アセンブリコードをチェックして、呼び出し時に関数コードがインライン化されているかどうかを確認できます。
アセンブリコードの生成方法
gccの場合:
コンパイル中に-S
スイッチを使用します。
例:
g++ -S FileName.cpp
生成されたアセンブリコードは、ファイルFileName.s
として作成されます。
MSVCの場合:
コマンドラインから/ FAスイッチを使用します。
特定の関数にcall
アセンブリ命令がある場合、生成されたアセンブリコードルックアップで。
一部のコンパイラーは、インライン関数要求に準拠できなかった場合に警告を発します。
たとえば、gccでは、コンパイラーがインラインで宣言された関数をインライン化しない場合、-Winline
コマンドオプションは警告を発します。
詳細については、GCCドキュメントを確認してください。
-Winline
インラインとして宣言された関数をインライン化できない場合に警告します。このオプションを使用しても、コンパイラはシステムヘッダーで宣言された関数のインライン化の失敗について警告しません。
コンパイラーは、さまざまなヒューリスティックを使用して、関数をインライン化するかどうかを決定します。たとえば、コンパイラーは、インライン化される関数のサイズと、現在の関数で既に行われているインライン化の量を考慮します。そのため、ソースプログラムにわずかな変更を加えただけで、
-Winline
によって生成された警告が表示または非表示になる可能性があります。
生成されたコードを確認してください。関数が展開されると、call
または同様の命令とは対照的に、その本体が表示されます。
Linuxの nm
などのオブジェクトファイルからシンボルをリストするツールを使用できます。関数がインライン化された場合、nm
出力にはリストされません-他の関数の一部になりました。また、デバッガーでこの関数にブレークポイントを名前で配置することもできません。
関数がインライン化されていて、MS VC++の独自の拡張機能を使用できることを確認する必要がある場合は、 __forceinline
宣言子を確認してください です。コンパイラーは関数をインライン化するか、それが文書化された特殊なケースのリストに該当する場合は警告が表示され、インライン化のステータスがわかります。
決してそれを支持しない。
Gdbでは、関数を呼び出すことができない場合、その可能な意味の1つは、関数がインラインであることです。推論を反転すると、gdb内で関数を呼び出すことができる場合、その関数はインラインとしてマークされません。
関数をインライン化するかどうかの決定は、コンパイラーによって行われます。また、コンパイラで作成されているため、コンパイル時にのみ作成できます。
したがって、-Sオプションを使用してアセンブリコードを表示できる場合(gcc -Sを使用するとアセンブリコードが生成されます)、関数がインライン化されているかどうかを確認できます。
上記の答えは非常に有用です。インライン関数を書くときに心に留めておく点を追加します。
インライン化はコンパイラへの要求であり、コマンドではないことに注意してください。コンパイラーはインライン化の要求を無視できます。 のような状況では、コンパイラーはインライン展開を実行できません。
1)関数にループが含まれている場合。 (のため、しばらくの間、do-while)
2)関数に静的変数が含まれている場合。
3)関数が再帰的である場合。
4)関数の戻り値の型がvoid以外であり、returnステートメントが関数本体に存在しない場合。
5)関数にswitchまたはgotoステートメントが含まれている場合。