標籤:lan too 編譯 需要 執行時間 com 位置 line src
目錄
- 什麼是內嵌函式
- 如何使函數內聯
- 為什麼要使用內嵌函式
- inline函數的優缺點分析
- 什麼時候該使用內嵌函式
本文
在C語言中,我們使用宏定義函數這種藉助編譯器的最佳化技術來減少程式的執行時間,那麼在C++中有沒有相同的技術或者更好的實現方法呢?答案是有的,那就是內嵌函式。內嵌函式作為編譯器最佳化手段的一種技術,在降低已耗用時間上非常有用。我們將從:
- 什麼是內嵌函式
- 為什麼要使用內嵌函式
- 內嵌函式優缺點分析
- 何時使用內嵌函式
這四個方面對內嵌函式進行介紹。
什麼是內嵌函式
內嵌函式是C++的增強特性之一,用來降低程式的已耗用時間。當內嵌函式收到編譯器的指示時,即可發生內聯:編譯器將使用函數的定義體來替代函數調用語句,這種替代行為發生在編譯階段而非程式運行階段。
值得注意的是,內嵌函式僅僅是對編譯器的內聯建議,編譯器是否覺得採取你的建議取決於函數是否符合內聯的有利條件。如何函數體非常大,那麼編譯器將忽略函數的內聯聲明,而將內嵌函式作為普通函數處理。
如何使函數內聯
定義函數時,在函數的最前面以關鍵字“inline”聲明函數,即可使函數稱為內聯聲明函數。
例如:
Class A{ Public: inline int add(int a, int b) { return (a + b); };}
Class A{ Public: int add(int a, int b);};
inline int A::add(int a, int b){ return (a + b);}
為什麼要使用內嵌函式
有時候我們會寫一些功能專一的函數,這些函數的函數體不大,包含了很少的執行語句。例如在計算1~1000以內的素數時,我們經常會使用開方操作使運算範圍縮小,這時我們會寫一個函數:
int root(int n){ return (int)sqrt((float)n);}
然後我們的求範圍內素數的函數可以這樣寫。
int prime(int n){ int i; for (i = 2; i <= root(n); i++) { if (n%i == 0) return 0; return 1; }}
當然,把root函數放在迴圈中不是個不明智的選擇,但想象一下,在某個程式上下文內必須頻繁地調用某個類似root的函數,其調用函數的花銷會有多大:當遇到普通函數的調用指令時,程式會儲存當前函數的執行現場,將函數中的局部變數以及函數地址壓入堆棧,然後再將即將調用的新函數載入到記憶體中,這要經曆複製參數值、跳轉到所調用函數的記憶體位置、執行函數代碼、儲存函數傳回值等過程,當函數執行完後,再擷取之前正在調用的函數的地址,回去繼續執行那個函數,已耗用時間開銷簡直太多了。
C++內嵌函式提供了替代函數調用的方案,通過inline聲明,編譯器首先在函數調用處使用函數體本身語句替換了函數調用語句,然後編譯替換後的代碼。因此,通過內嵌函式,編譯器不需要跳轉到記憶體其他地址去執行函數調用,也不需要保留函數調用時的現場資料。
inline函數的優缺點分析
通過下面這些優缺點總結你大概會更理解為什麼要使用inline函數:
優點:
- 它通過避免函數調用所帶來的開銷來提高你程式的運行速度。
- 當函數調用發生時,它節省了變數彈棧、壓棧的開銷。
- 它避免了一個函數執行完返回原現場的開銷。
- 通過將函式宣告為內聯,你可以把函數定義放在標頭檔內。
缺點:
- 因為代碼的擴充,內嵌函式增大了可執行程式的體積。
- C++內嵌函式的展開是中編譯階段,這就意味著如果你的內嵌函式發生了改動,那麼就需要重新編譯代碼。
- 當你把內嵌函式放在標頭檔中時,它將會使你的標頭檔資訊變多,不過標頭檔的使用者不用在意這些。
- 有時候內嵌函式並不受到青睞,比如在嵌入式系統中,嵌入式系統的儲存約束可能不允許體積很大的可執行程式。
什麼時候該使用內嵌函式
當程式設計需要時,每個函數都可以聲明為inline。下面列舉一些有用的建議:
- 當對程式執行效能有要求時,那麼就使用內嵌函式吧。
- 當你想宏定義一個函數時,那就果斷使用內嵌函式吧。
- 在類內部定義的函數會預設聲明為inline函數,這有利於 類實現細節的隱藏。
關鍵點
- 內聯聲明只是一種對編譯器的建議,編譯器是否採用內聯措施由編譯器自己來決定。甚至在彙編階段或連結階段,一些沒有inline聲明的函數編譯器也會將它內聯展開。
- 編譯器的內聯看起來就像是代碼的複製與粘貼,這與預先處理宏是很不同的:宏是強制的內聯展開,可能將會汙染所有的命名空間與代碼,將為程式的調試帶來困難。
- 所有中類中定義的函數都預設聲明為inline函數,所有我們不用顯示地去聲明inline。
- 虛函數不允許內聯。
- 雖然說模板函數放中標頭檔中,但它們不一定是內聯的。(不是說定義在標頭檔中的函數都是內嵌函式)。
轉自:http://www.cnblogs.com/QG-whz/p/4641479.html
C++內嵌函式