C++では、クラスメンバー関数を以下のように宣言できます:
クラス内で(インライン定義):
class A { void foo() { /* ... */ } // クラス内で直接 };
このような関数は暗黙的に inline と見なされます。
クラス内で(宣言のみ):
class A { void foo(); // 宣言のみ }; void A::foo() { /* ... */ } // クラス外での定義
違い:
inline を想定し、コンパイラはその関数を呼び出しのコードに埋め込むことができます。inline とはならず、明示的に指定する必要があります(inline)。これは以下のように追加できます:
inline void A::foo() { /* ... */ }
アプローチの利点と欠点:
クラス内で定義された関数は、必ずコンパイラによって実際にインライン化されるのでしょうか?
答え:いいえ。 inline というキーワード(クラス内での暗黙的な割り当てを含む)は、コンパイラへの単なる提案です。コンパイラは、その関数をインライン化することがあまりにも複雑または不適切と見なした場合、この提案を無視することがあります。
物語 1
大規模プロジェクトで、クラスメンバー関数がヘッダーファイル内で
inlineとして定義され、何千もの翻訳単位に含まれた結果、コンパイル時間が数倍に増加し、コードの重複によりバイナリが増大しました — コンパイラは常に同一の機械実装を統合するわけではありません。
物語 2
実行速度を向上させるために、開発者はクラスの全ロジックを宣言に移しました(.hファイル)。これにより、関数が変更される度にプロジェクト全体が再コンパイルされ、実際に統合が影響を受けるファイルのみが影響を受けるわけではありませんでした。
物語 3
チームの新しいメンバーが、テンプレートクラスの宣言に長いシリアライズメソッドとファイル操作メソッドを直接置いたため、エラーがすべてのTUにわたって偶発的に拡散し、実行ファイルのサイズが増大しながらパフォーマンスの向上が見られませんでした。