內聯函式與巨集

2021-07-22 07:52:54 字數 1445 閱讀 9312

當函式被宣告為內聯函式之後, 編譯器會將其內聯展開, 而不是按通常的函式呼叫機制進行呼叫.

內聯函式不是在呼叫時發生控制轉移,而是在編譯時將函式體嵌入在每乙個呼叫處。編譯時,類似巨集替換,使用函式體替換呼叫處的函式名。一般在**中用inline修飾,但是能否形成內聯函式,需要看編譯器對該函式定義的具體處理。

內聯是用來消除函式呼叫時的時間開銷。它通常用於頻繁執行的函式。 乙個小記憶體空間的函式非常受益。

如果沒有內聯函式,編譯器可以決定哪些函式內聯 。 程式設計師很少或沒有控制哪些只能是內聯的,哪些不是。 給這種控制程度,作用是程式設計師可以選擇內聯的特定應用 。

只要內聯的函式體較小,內聯該函式可以令目標**更加高效. 對於訪問函式以及其它函式體比較短,效能關鍵的函式, 鼓勵使用內聯.

濫用內聯將導致程式變得更慢. 內聯可能使目標**量或增或減, 這取決於內聯函式的大小. 內聯非常短小的訪問函式通常會減少**大小, 但內聯乙個相當大的函式將戲劇性的增加**大小. 現代處理器由於更好的利用了指令快取, 小巧的**往往執行更快。

乙個較為合理的經驗準則是,不要內聯超過 10 行的函式.謹慎對待析構函式, 析構函式往往比其表面看起來要更長, 因為有隱含的成員和基類析構函式被呼叫!

另乙個實用的經驗準則: 內聯那些包含迴圈或 switch 語句的函式常常是得不償失 (除非在大多數情況下, 這些迴圈或 switch 語句從不被執行).

有些函式即使宣告為內聯的也不一定會被編譯器內聯, 這點很重要;

比如虛函式和遞迴函式就不會被正常內聯.

通常, 遞迴函式不應該宣告成內聯函式.

(yulefox 注: 遞迴呼叫堆疊的展開並不像迴圈那麼簡單, 比如遞迴層數在編譯時可能是未知的, 大多數編譯器都不支援內聯遞迴函式). 虛函式內聯的主要原因則是想把它的函式體放在類定義內, 為了圖個方便, 抑或是當作文件描述其行為, 比如精短的訪問函式.

內聯函式的功能和預處理巨集的功能相似。相信大家都用過預處理巨集,我們會經常定義一些巨集,如

#define table_comp(x) ((x)>0?(x):0)
就定義了乙個巨集。

為什麼要使用巨集呢?因為函式的呼叫必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作要求在轉去執行前要儲存現場並記憶執行的位址,轉回後要恢復現場,並按原來儲存位址繼續執行。因此,函式呼叫要有一定的時間和空間方面的開銷,將影響其效率。而巨集只是在預處理的地方把**展開,不需要額外的空間和時間方面的開銷,所以呼叫乙個巨集比呼叫乙個函式更有效率。

但是巨集也有很多的不盡人意的地方。

巨集不能訪問物件的私有成員。

巨集的定義很容易產生二義性。

本文內容來自:

google開源**風格指南,稍作整理修改。

巨集與內聯函式

函式作為一種抽象機制,對解決大型複雜問題起到了很大作用。但是,由於函式呼叫時需要開銷的,例如,函式呼叫時需要保護呼叫者的執行環境,進行引數傳遞,執行呼叫命令,為區域性變數分配空間以及執行返回指令等,因此函式會帶來程式執行效率的下降,特別是對一些小函式的頻繁呼叫。c 提供了兩種解決上述問題的辦法 巨集...

巨集與內聯函式

建議 1 使用const定義常量而不是 define 2 使用inline內聯函式而不是 define來定義小型函式 第一部分 巨集 為什麼要使用巨集呢?因為函式的呼叫 必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作...

巨集與內聯函式

第一部分 巨集 為什麼要使用巨集呢?因為函式的呼叫必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作要求在轉去執行前要儲存現場並記憶執行的位址,轉回後要恢復現場,並按原來儲存位址繼續執行。因此,函式呼叫要有一定的時間和空...