名前空間
変種
操作

inline 指定子

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

inline 指定子は、関数の decl-specifier-seq で使用されたとき、その関数をインライン関数であると宣言します。

class/struct/union の定義内部で完全に定義された関数は、それがメンバ関数であるか非メンバの friend 関数であるかにかかわらず、暗黙にインライン関数です。

constexpr 宣言された関数は暗黙にインライン関数です。

削除された関数は暗黙にインライン関数です。 その (削除された) 定義は複数の翻訳単位内に現れることができます。

(C++11以上)

inline 指定子は、静的記憶域期間を持つ変数 (静的クラスメンバまたは名前空間スコープの変数) の decl-specifier-seq で使用されたとき、その変数をインライン変数であると宣言します。

constexpr 宣言された静的メンバ変数は暗黙にインライン変数です (名前空間スコープの変数はそうではありません)。

(C++17以上)

目次

[編集] 説明

インライン関数またはインライン変数 (C++17以上)は以下の性質を持ちます。

  1. インライン関数またはインライン変数 (C++17以上)の定義は、それがアクセスされる翻訳単位内で到達可能でなければなりません (アクセスの地点より前である必要はありません)。
  2. 外部リンケージを持つ (例えば static 宣言されていない) インライン関数またはインライン変数 (C++17以上)は、以下の追加の性質を持ちます。
  1. 各定義が異なる翻訳単位内に現れ、 (非静的インライン関数および変数 (C++17以上)の場合は) すべての定義が同一である限り、1つのインライン関数またはインライン変数 (C++17以上)複数の定義がプログラム内に存在しても構いません。 例えば、インライン関数またはインライン変数 (C++17以上)を複数のソースファイルから #include されるヘッダファイル内で定義しても構いません。
  2. すべての翻訳単位内で inline 宣言されなければなりません。
  3. すべての翻訳単位内で同じアドレスを持ちます。

インライン関数では、

  • すべての関数定義内の関数ローカルな静的オブジェクトはすべての翻訳単位に渡って共有されます (それらすべてがある翻訳単位で定義された同じオブジェクトを参照します)。
  • すべての関数定義内で定義された型もすべての翻訳単位内で同じです。
  • すべての関数定義内の文字列リテラルは共有されます (それらはすべてある翻訳単位内で定義された同じ文字列リテラルです)。
(C++17未満)

名前空間スコープのインライン const 変数は (非インライン非 volatile な const 修飾された変数と異なり) デフォルトで外部リンケージを持ちます。

(C++17以上)

inline キーワードの元々の意図は、関数呼び出しよりも関数のインライン置換を好む、つまり、制御を関数の本体に移す関数呼び出しの CPU 命令を実行する代わりに関数本体のコピーを呼び出しを生成せずに実行することのインジケータとして最適化に提供するためのものでした。 これは関数呼び出しによって生じるオーバーヘッド (引数渡しと戻り値の受け取り) を回避しますが、関数のコードが複数回繰り返される必要があるため実行可能形式がより大きくなる可能性がありました。

キーワード inline のこの意味には拘束力がないため、コンパイラは inline としてマークされていない任意の関数に対してインライン置換を用いる自由があり、 inline としてマークされている任意の関数への関数呼び出しを生成する自由があります。 これらの最適化の選択は複数回の定義および上記の静的の共有に関するルールを変更しません。

関数に対する inline キーワードの意味は「インライン化が好ましい」ではなく「複数回の定義が許される」という意味になったため、この意味が変数に拡張されました。

(C++17以上)

[編集] ノート

外部リンケージを持つインライン関数またはインライン変数 (C++17以上)が異なる翻訳単位で異なって定義される場合、動作は未定義です。

inline 指定子はブロックスコープの (別の関数内部の) 関数または変数 (C++17以上)の宣言で使用することはできません。

inline 指定子は翻訳単位内で非インラインとしてすでに定義された関数または変数 (C++17以上)を再宣言することはできません。

暗黙に生成されたメンバ関数およびその最初の宣言においてデフォルト化として宣言されたあらゆるメンバ関数は、クラス定義内部で定義された他のあらゆる関数と同様に、インラインです。

インライン関数が異なる翻訳単位で宣言された場合、各翻訳単位の終わりにおいてデフォルト引数の蓄積された集合が同じでなければなりません。

C では、インライン関数はすべての翻訳単位内でインライン宣言する必要はなく (最大1個が非 inline または extern inline であることができます)、関数定義が同じである必要はなく (しかしプログラムの動作はいずれが呼ばれるかに依存してはなりません)、関数ローカルな静的は同じ関数の異なる定義間で別々です。

インライン静的メンバに関する追加のルールについて静的データメンバを参照してください。

インライン変数は C++ のコードをヘッダオンリーなライブラリとしてパッケージ化するための主要な障害を取り除きます。

(C++17以上)

[編集]

// ヘッダファイル
#ifndef EXAMPLE_H
#define EXAMPLE_H
// 複数のソースファイルでインクルードされる関数はインラインでなければなりません。
inline int sum(int a, int b) 
{
    return a + b;
}
#endif
 
// ソースファイル #2
#include "example.h"
int a()
{
    return sum(1, 2);
}
 
// ソースファイル #1
#include "example.h"
int b()
{
    return sum(3, 4);
}


[編集] 関連項目