inline
specifier
inline 指定子は、関数の decl-specifier-seq で使用された場合、その関数を インライン関数 として宣言します。
クラス/構造体/共用体定義内で完全に定義された関数は、 クラス/構造体/共用体定義 内で完全に定義された関数は、メンバー関数であるか非メンバーの friend 関数であるかに関わらず、暗黙的にインライン関数となります (ただし、 名前付きモジュール に属する場合を除く (C++20以降) 。
|
最初の宣言で constexpr または consteval (C++20以降) と宣言された関数は、暗黙的にインライン関数となる。 削除された関数は暗黙的にインライン関数となる:その(削除された)定義は複数の翻訳単位に現れることができる。 |
(C++11以降) |
|
inline 指定子は、静的ストレージ期間を持つ変数(静的クラスメンバまたは名前空間スコープの変数)の decl-specifier-seq で使用された場合、その変数を インライン変数 として宣言する。 最初の宣言で constexpr と宣言された静的データメンバは、暗黙的にインライン変数となる。 |
(C++17以降) |
目次 |
説明
インライン関数 またはインライン変数 (C++17以降) は以下の特性を持ちます:
- inline関数 または変数 (C++17以降) の定義は、それがアクセスされる翻訳単位で到達可能でなければならない(必ずしもアクセス時点より前である必要はない)。
- 外部リンケージを持つinline関数 または変数 (C++17以降) (例えば static として宣言されていないもの)は、以下の追加の特性を持つ:
-
- インライン関数 または変数 (C++17以降) は、各定義が異なる翻訳単位に現れ、かつ(非staticなインライン関数 および変数 (C++17以降) の場合)すべての定義が同一であれば、プログラム内に 複数の定義 が存在してもよい。例えば、インライン関数 またはインライン変数 (C++17以降) は、複数のソースファイルにインクルードされるヘッダファイルで定義することができる。
- すべての翻訳単位で inline として宣言されていなければならない。
- すべての翻訳単位で同じアドレスを持つ。
インライン関数では、
- すべての関数定義内の関数ローカル静的オブジェクトは、すべての翻訳単位で共有されます(それらはすべて、1つの翻訳単位で定義された同じオブジェクトを参照します)。
- すべての関数定義内で定義された型も、すべての翻訳単位で同じです。
|
名前空間スコープでのインラインconst変数は、デフォルトで 外部リンケージ を持ちます(非インラインで非volatileのconst修飾変数とは異なります)。 |
(C++17以降) |
inline キーワードの本来の意図は、関数呼び出しよりも 関数のインライン展開 が優先されることをオプティマイザに示すことであった。つまり、関数本体に制御を転送する関数呼び出しCPU命令を実行する代わりに、呼び出しを生成せずに関数本体のコピーが実行される。これにより、関数呼び出しによって生じるオーバーヘッド(引数の受け渡しと結果の取得)が回避されるが、関数のコードが複数回繰り返されるため、実行可能ファイルのサイズが大きくなる可能性がある。
インライン置換は標準セマンティクスにおいて観測不可能であるため、コンパイラは inline とマークされていない任意の関数に対してインライン置換を使用する自由があり、 inline とマークされた任意の関数に対して関数呼び出しを生成する自由があります。これらの最適化の選択は、前述の多重定義と共有静的変数に関する規則を変更しません。
|
C++98以降、関数に対するキーワード inline の意味が「インライン化が推奨される」ではなく「複数の定義が許可される」という意味になったため、その意味が変数にも拡張されました。 |
(since C++17) |
注記
外部リンケージを持つインライン関数 または変数 (C++17以降) が異なる翻訳単位で異なる定義を持つ場合、プログラムは不適格(ill-formed)となり、診断は要求されません。
inline 指定子は、ブロックスコープ(他の関数内)での関数 または変数 (C++17以降) の宣言では使用できません。
inline 指定子は、翻訳単位で既に非inlineとして定義されている関数 または変数 (C++17以降) を再宣言することはできません。
クラス定義内で定義される他の関数と同様に、暗黙的に生成されるメンバー関数および最初の宣言でdefaultedとして宣言されたメンバー関数はinlineとなります。
インライン関数が異なる翻訳単位で宣言される場合、蓄積された デフォルト引数 の集合は、各翻訳単位の終端で同一でなければなりません。
C言語では、インライン関数はすべての翻訳単位で inline と宣言される必要はありません(多くとも一つが非 inline または extern inline であっても構いません)。関数定義は同一である必要はありません(ただし、どちらが呼び出されるかに依存する場合、プログラムの動作は未定義です)。また、関数内のstatic変数は、同じ関数の異なる定義間で独立しています。
|
インライン静的メンバーに関する追加の規則については static data members を参照してください。 インライン変数は、C++コードをヘッダーのみのライブラリとしてパッケージ化する際の主な障害を排除します。 |
(C++17以降) |
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_inline_variables
|
201606L
|
(C++17) | Inline variables |
キーワード
例
ヘッダーファイル "example.h":
#ifndef EXAMPLE_H #define EXAMPLE_H #include <atomic> // 複数のソースファイルに含まれる関数はinlineでなければならない inline int sum(int a, int b) { return a + b; } // 外部リンケージを持つ変数で複数のソースファイルに含まれるものはinlineでなければならない inline std::atomic<int> counter(0); #endif
ソースファイル #1:
#include "example.h" int a() { ++counter; return sum(1, 2); }
ソースファイル #2:
#include "example.h" int b() { ++counter; return sum(3, 4); }
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 281 | C++98 |
フレンド関数宣言が、フレンド指定された関数がインライン関数でない場合でも
inline指定子を使用できた |
このような使用を禁止 |
| CWG 317 | C++98 |
宣言の前に同じ翻訳単位内に非インラインの定義がある場合でも
関数をinline宣言できた |
この場合プログラムは
不適格 |
| CWG 765 | C++98 |
インライン関数内で定義された型が異なる翻訳単位で
異なる可能性があった |
そのような型は全ての翻訳単位で
同じである |
| CWG 1823 | C++98 |
インライン関数の全ての定義内の文字列リテラルが
全ての翻訳単位で共有されていた |
一貫性と実装の都合により
要件が削除された |
| CWG 2531 | C++17 |
静的データメンバーが最初の宣言で
constexpr
宣言されていなくても
暗黙的にinlineになり得た |
この場合、暗黙的に
inlineにはならない |
関連項目
|
Cドキュメント
の
inline
|