介紹
C++ 新增了 inline 關鍵字,可以為函數定義加上前綴,例如:
inline int max_int( int a, int b ) { return a > b ? a : b; }
給編譯器一個“提示”,程式整體上可能會從函數內聯中受益於效能。
已內聯的函數在呼叫它的每個點都會擴展其程式碼,而不是執行以下正常的函數呼叫機制:
- 保存暫存器。
- 將參數值壓入堆疊。
- 執行呼叫指令。
- 函數最後執行ret指令。
- 恢復暫存器。
對於非常小的函數,內聯可以提高效能。 但就像大多數其他事情一樣,也需要權衡。
內嵌關鍵字已向後移植到 C99,但要求略有不同 - 稍後會詳細介紹。
與巨集的區別
內聯函數就像(並且旨在取代)類似函數的宏。 一般來說,這是一件好事,因為內聯函數 是 函數,並且具有完整的函數語義,而不是僅由不理解 C 或 C++ 的預處理器完成的文字替換。
與 max_int() 函數等效的巨集:
#define MAX_INT(A,B) A > B ? A : B /* bad implementation */
有以下問題:
- 擴充參數,例如 MAX(n & 0xFF, 8),可能會導致錯誤的運算子優先權。
- 有副作用的參數,例如 MAX(n++, 8),可能有多個副作用。
- 定義時不對參數進行型別檢查。
- 錯誤通常很冗長且難以閱讀。
另外,一個宏:
- 可以修改它的參數(這通常不是你想要的)。
內聯函數不存在這些問題,但可以產生相同的效能優勢。 因此,請使用內聯函數而不是類似函數的巨集。
只是一個提示
如前所述,指定內聯只是對編譯器的一個“提示”,即程式總體上可能會從內聯函數中受益於性能。 編譯器可以隨意忽略提示。
為什麼? 因為在某些情況下,這要么不是一個好主意,要么是不可能的。 當滿足以下任一條件時,函數要麼不內聯,要麼通常不內聯:
- 功能「太大」。
- 您透過函數指標呼叫函數。
- 函數是遞歸的。
- 該函數有一個循環。
可能還有其他原因。這一切都高度依賴函數、其參數、編譯器以及為其提供的任何選項。
如果編譯器不能或選擇不內聯函數,它會不警告您它尚未這樣做(預設)。 一些編譯器,例如 gcc,有一個 -Winline 選項,它會警告您並給出函數未內聯的原因。
指定內聯類似於指定暫存器的舊程式碼 - 它們都只是提示。
何時(以及何時不)內聯
對大多數函數來說,執行函數的大部分成本都在函數體中,而不是在函數呼叫機制中。 因此,為了使函數成為內聯的良好候選者,它通常必須是:
- 夠小,使得函數呼叫機制的成本占主導地位。
- 用於性能真正重要的地方,例如緊密循環。
如有疑問,請分析您的程式碼。 使用內聯不是神奇的「讓我更快」關鍵字。 此外,過度使用內聯可能會導致程式碼膨脹,從而進一步使程式的效能整體更差。
有關更多信息,請參閱內聯疾病。
通常適合內聯的函數包括:
- “單行程式碼”,例如“getters”和“setters”。
- 對其他函數呼叫的簡單包裝器,為參數提供特定值或進行強制轉換。
理想的內嵌函數既提高效能又減少程式碼大小。
但是,任何內聯函數的一個警告是,如果其定義發生更改,則需要重新編譯所有使用它的程式碼。
內聯優化
如果內聯函數實際上是由編譯器內聯的,那麼,除了省略正常函數呼叫機制的程式碼之外,編譯器還可以:
- Eliminate one or more function arguments completely whose values are constants via immediate addressing.
- Perform better optimizations spanning the code the function is inlined into that it normally couldn’t perform across function boundaries.
Inline Function Definition
In order for the compiler to be able to inline a function, it has to be able to “see” its definition (not just its declaration) in every .c or .cpp file it’s used in just like a macro. Hence, an inline function must be defined in a header file.
Normally, a function, like everything else, must have exactly one definition by adhering to the one definition rule (ODR). However, since the definition of an inline function is “seen” in multiple .c or .cpp files, the ODR is suspended for that function.
It is possible to have different definitions for inline functions having the same name, but this results in undefined behavior since the compiler has no way to check that every definition is the same.
To inline a function in C++, all you need do is prefix the function definition with inline — that’s it. The compiler and/or linker will automatically discard all but one definition from the final executable file for you.
However, to inline a function in C, you additionally must explicitly tell the compiler into what .o file to put the one definition in the event the compiler is either unable or unwilling to inline a function via extern inline.
For example, in exactly one .c file, you would declare a function like:
// util.c extern inline int max_int( int, int );
That tells the compiler to “put the one definition for max_int() into util.o.”
Alternatively in C, you can instead declare an inline function static also:
static inline int max_int( int a, int b ) { return a > b ? a : b; }
If you do this, then:
- You do not have to declare a function extern inline anywhere.
- However, if the compiler doesn’t inline a function, it will generate a definition in every .c file it’s included into again leading to code bloat.
- If the function has any static local variables, every definition will have distinct copies (that may or may not be what you want).
Conclusion
Inline functions, if used judiciously, can yield performance gains. Generally, only very small functions are good candidates for inlining.
Starting in C++11, inline functions can alternatively be declared constexpr, but that’s a story for another time.
References
- Linux kernel coding style, §15 The inline disease.
- Myth and reality about inline in C99.
- The Annotated C++ Reference Manual, Margaret A. Ellis & Bjarne Stroustrup, Addison-Wesley, 1990, ISBN 0-201-51459-1, §7.1.2 Function Specifiers, pp. 99–105.
以上是C 和 C++ 中的內聯函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Gulc是一個高性能的C庫,優先考慮最小開銷,積極的內襯和編譯器優化。 其設計非常適合高頻交易和嵌入式系統等關鍵應用程序,其設計強調簡單性,模型

本文詳細介紹了C函數返回類型,包括基本(int,float,char等),派生(數組,指針,結構)和void類型。 編譯器通過函數聲明和返回語句確定返回類型,執行

本文解釋了C函數聲明與定義,參數傳遞(按值和指針),返回值以及常見的陷阱,例如內存洩漏和類型不匹配。 它強調了聲明對模塊化和省份的重要性

本文詳細介紹了字符串案例轉換的C功能。 它可以通過ctype.h的toupper()和tolower()解釋,並通過字符串迭代並處理零終端。 常見的陷阱,例如忘記ctype.h和修改字符串文字是

本文研究C函數返回值存儲。 較小的返回值通常存儲在寄存器中以備速度;較大的值可能會使用指針來記憶(堆棧或堆),影響壽命並需要手動內存管理。直接ACC

本文分析了形容詞“獨特”的多方面用途,探索其語法功能,常見的短語(例如,“不同於”,“完全不同”),以及在正式與非正式中的細微應用

本文解釋了C標準模板庫(STL),重點關注其核心組件:容器,迭代器,算法和函子。 它詳細介紹了這些如何交互以啟用通用編程,提高代碼效率和可讀性t

本文詳細介紹了c中有效的STL算法用法。 它強調了數據結構選擇(向量與列表),算法複雜性分析(例如,std :: sort vs. std vs. std :: partial_sort),迭代器用法和並行執行。 常見的陷阱


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具