インライン関数
クラス:インデックス への移動
メンバー関数は,クラスの中で宣言してほかの場所で定義することができます。また,クラスの中で宣言と定義の両方を行うこともでき,この場合のメンバー関数はインライン関数と呼ばれます。
コンパイラは,関数呼び出しの位置に関数本体のコンパイルされたコードを直接埋め込むことによって,通常の関数呼び出しにおけるオーバーヘッドを減少させることができます。このプロセスは,関数本体のインライン展開と呼ばれますが,関数名と引数のスコープには影響を与えません。インライン展開は,常に可能なわけではありません。インライン指定子で,コンパイラにインライン展開を指示します。
メモ: コンパイラはインライン展開要求を無視できます。
明示的あるいは暗黙的な inline 要求は,オーバーロードされた演算子を実現する演算子関数のような,小さくて頻繁に使用される関数には適しています。たとえば,次の func のクラス宣言は,
int i; // グローバルな int
class X {
public:
char* func(void) { return i; } // デフォルトではインライン
char* i;
};
次の宣言と同じです。
inline char* X::func(void) { return i; }
func は,明示的なインライン指定子とともにクラスの「外部で」定義されています。func が返す値 i は,クラス X の char*i です(メンバーのスコープを参照)。
インライン関数と例外
コンラパイラは,例外処理が指定されたインライン関数はインライン展開できません。次に例を示します。
inline void f1() throw(int)
{
// 警告: 例外処理が指定された関数はインライン展開できない
}
以下に示す制限は,デストラクタによる後始末が有効な場合にのみ適用されます。
メモ: デフォルトでデストラクタが呼び出されます。例外処理のオプションについては,例外処理オプション(-x,-xf,-xp) を参照してください。
「デストラクタを持つクラス」型のパラメータが 1 つでも指定されたインライン関数は,インライン展開されません。この制限は,参照渡しのクラスには適用されないことに注意してください。次に例を示します。
struct foo {
foo();
~foo();
};
inline void f2(foo& x)
{
// 警告なし。f2() はインライン展開できる
}
inline void f3(foo x)
{
// 警告: 値渡しのクラスの引数をとる関数は
// 関数 f3(foo) でインライン展開されない
}
デストラクタを持つクラスを値渡しで返すインライン関数は,return 式の中で破棄されなければならない変数や一時オブジェクトがある場合は,常にインライン展開されません。
struct foo {
foo();
~foo();
};
inline foo f4()
{
return foo();
// 警告なし。f4() はインライン展開される
}
inline foo f5()
{
foo X;
return foo(); // オブジェクト X は破棄されなければならない
// 警告: return 文をいくつか含む関数は
// 関数 f5() でインライン展開されない
}
inline foo f6()
{
return ( foo(), foo() ); // 戻り値は一時的な値
// 警告: return 文をいくつか含む関数は
// 関数 f6() でインライン展開されない
}