命名空間
變體
動作

inline 指定符

出自 cppreference.com
< cpp‎ | language
 
 
C++ 語言
一般主題
流程控制
條件執行陳述式
if
疊代陳述式 (迴圈)
for
範圍 for (C++11)
跳躍陳述式
函式
函式宣告
Lambda 函式運算式
inline 指定符
動態例外規範 (直到 C++17*)
noexcept 指定符 (C++11)
例外
命名空間
型別
指定符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
儲存期指定符
初始化
 
 

inline 指定子在用於函式的 decl-specifier-seq 時,會將該函式宣告為 inline 函式 (inline function)

完全定義在 class/struct/union 定義內部的函式,不論是成員函式或是非成員的 friend 函式,皆隱含地為 inline 函式,除非其被附加至某個具名模組(自 C++20 起)

在首次宣告時即被宣告為 constexprconsteval(自 C++20 起) 的函式,隱含地為 inline 函式。

被刪除 (deleted) 的函式隱含地為 inline 函式:其(已刪除的)定義可以出現在多個編譯單元(translation unit)中。

(C++11 起)

inline 指定子在用於具靜態儲存期變數(靜態類別成員或命名空間範圍變數)的 decl-specifier-seq 時,會將該變數宣告為 inline 變數 (inline variable)

在首次宣告時即被宣告為 constexpr 的靜態資料成員,隱含地為 inline 變數。

(自 C++17 起)

目錄

[編輯] 說明

inline 函式或 inline 變數(自 C++17 起)具有下列性質:

  • inline 函式或變數(自 C++17 起)的定義必須在存取它的編譯單元中是可達(reachable)的(不一定要在存取點之前)。
  • 具有 外部連結性 (external linkage)(例如未宣告為 static)的 inline 函式或變數(自 C++17 起)具有下列額外性質:
  • 程式中可以有超過一個 inline 函式或變數(自 C++17 起)的定義,只要每個定義出現在不同的編譯單元中,且(對於非靜態 inline 函式及變數(自 C++17 起))所有定義皆相同。例如,inline 函式或 inline 變數(自 C++17 起)可以定義在包含於多個原始碼檔案的標頭檔中。
  • 它必須在每個編譯單元中都被宣告為 inline
  • 它在每個編譯單元中都具有相同的位址。

在 inline 函式中:

  • 所有函式定義中的「函式區域靜態物件 (function-local static objects)」在所有編譯單元之間共用(它們都指向定義在一個編譯單元中的同一個物件)。
  • 所有函式定義中定義的型別,在所有編譯單元中也都相同。

在命名空間範圍的 inline const 變數預設具有 外部連結性(不同於非 inline、非 volatile 的 const 限定變數)。

(自 C++17 起)

inline 關鍵字的最初意圖是作為一種指示,告訴優化器:比起函式呼叫,更偏好函式的 inline 替換 (inline substitution);也就是說,不執行轉移控制權至函式本體的 CPU 函式呼叫指令,而是直接執行函式本體的副本,而不產生呼叫。這避免了函式呼叫產生的開銷(傳遞參數及取得結果),但可能會導致執行檔變大,因為函式的程式碼必須重複多次。

由於 inline 替換在標準語義中是不可觀察的,編譯器可以自由地對任何未標記為 inline 的函式進行 inline 替換,也可以自由地對任何標記為 inline 的函式產生函式呼叫。這些優化選擇並不會改變上述關於多重定義和共用靜態變數的規則。

因為從 C++98 起,關鍵字 inline 對函式的意義變成了「允許重複定義」而非「偏好 inline 化」,該意義隨後也被擴展到了變數。

(自 C++17 起)

[編輯] 筆記

如果具有外部連結性的 inline 函式或變數(自 C++17 起)在不同編譯單元中的定義不一致,則程式格式錯誤 (ill-formed),且不要求診斷資訊。

inline 指定子不能用於塊範圍(block scope,即在另一個函式內部)的函式或變數(自 C++17 起)宣告。

inline 指定子不能重新宣告在同一個編譯單元中已被定義為非 inline 的函式或變數(自 C++17 起)

隱含產生的成員函式,以及任何在首次宣告時宣告為 defaulted 的成員函式,都像任何定義在類別定義內部的函式一樣,是 inline 的。

如果在不同編譯單元中宣告了某個 inline 函式,則在每個編譯單元結束時,累積的預設參數 (default arguments) 集合必須相同。

在 C 語言中,inline 函式不一定要在每個編譯單元中都被宣告為 inline(最多可以有一個非 inlineextern inline 定義),函式定義不一定要完全相同(但如果程式行為依賴於呼叫哪一個定義,則該行為是未定義的),且同一個函式的不同定義之間的函式區域靜態變數是各自獨立的。

關於 inline 靜態成員的額外規則,請參閱靜態資料成員

Inline 變數消除了將 C++ 程式碼打包為 header-only 函式庫的主要障礙。

(自 C++17 起)
特性測試巨集 數值 標準 功能
__cpp_inline_variables 201606L (C++17) Inline 變數

[編輯] 關鍵字

inline

[編輯] 範例

標頭檔 "example.h"

#ifndef EXAMPLE_H
#define EXAMPLE_H
 
#include <atomic>
 
// function included in multiple source files must be inline
inline int sum(int a, int b)
{
    return a + b;
}
 
// variable with external linkage included in multiple source files must be 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 friend 函式宣告可以使用 inline 指定子
即使被宣告為 friend 的函式本身並非 inline 函式
禁止此類用法
CWG 317 C++98 函式即使在同一個編譯單元中已被定義為非 inline
在其定義之後仍可被宣告為 inline
在這種情況下,程式格式錯誤
formed in this case
CWG 765 C++98 定義在 inline 函式中的型別可能
在不同編譯單元中有所不同
此類型別在所有
編譯單元中皆應相同
CWG 1823 C++98 inline 函式所有定義中的字串實字
需跨編譯單元共用
由於一致性與實作上的考量,
此項要求已被移除
CWG 2531 C++17 靜態資料成員即使未在首次宣告時
宣告為 constexpr,也可能隱含地為 inline
在此情況下它不應
隱含地為 inline

[編輯] 參閱

關於 inlineC 語言文件
English Deutsch 日本語 한국어 中文(简体) 中文(繁體)