關於inline函式

gudesheng發表於2008-01-03

(一)inline函式(摘自C++ Primer的第三版)

      在函式宣告或定義中函式返回型別前加上關鍵字inline即把min()指定為內聯。

      inline int min(int first, int secend) {/****/};

        inline函式對編譯器而言必須是可見的,以便它能夠在呼叫點內展開該函式。與非inline函式不同的是,inline函式必須在呼叫該函式的每個文字檔案中定義。當然,對於同一程式的不同檔案,如果inline函式出現的話,其定義必須相同。對於由兩個檔案compute.C和draw.C構成的程式來說,程式設計師不能定義這樣的min()函式,它在compute.C中指一件事情,而在draw.C中指另外一件事情。如果兩個定義不相同,程式將會有未定義的行為.

        為保證不會發生這樣的事情,建議把inline函式的定義放到標頭檔案中。在每個呼叫該inline函式的檔案中包含該標頭檔案。這種方法保證對每個inline函式只有一個定義,且程式設計師無需複製程式碼,並且不可能在程式的生命期中引起無意的不匹配的事情。

(二)行內函數的程式設計風格(摘自高質量C++/C 程式設計指南)

關鍵字inline 必須與函式定義體放在一起才能使函式成為內聯,僅將inline 放在函式宣告前面不起任何作用

如下風格的函式Foo 不能成為行內函數:
inline void Foo(int x, int y); // inline 僅與函式宣告放在一起
void Foo(int x, int y)
{
}
而如下風格的函式Foo 則成為行內函數:
void Foo(int x, int y);
inline void Foo(int x, int y) // inline 與函式定義體放在一起
{
}
所以說,inline 是一種“用於實現的關鍵字”,而不是一種“用於宣告的關鍵字”。一般地,使用者可以閱讀函式的宣告,但是看不到函式的定義。儘管在大多數教科書中行內函數的宣告、定義體前面都加了inline 關鍵字,但我認為inline 不應該出現在函式的宣告中。這個細節雖然不會影響函式的功能,但是體現了高質量C++/C 程式設計風格的一個基本原則:宣告與定義不可混為一談,使用者沒有必要、也不應該知道函式是否需要內聯。


定義在類宣告之中的成員函式將自動地成為行內函數,例如
class A
{
public:
void Foo(int x, int y) {  } // 自動地成為行內函數
}
將成員函式的定義體放在類宣告之中雖然能帶來書寫上的方便,但不是一種良好的程式設計
風格,上例應該改成:
// 標頭檔案
class A
{
public:
void Foo(int x, int y);
}
// 定義檔案
inline void A::Foo(int x, int y)
{
}

慎用內聯
內聯能提高函式的執行效率,為什麼不把所有的函式都定義成行內函數?
如果所有的函式都是行內函數,還用得著“內聯”這個關鍵字嗎?
內聯是以程式碼膨脹(複製)為代價,僅僅省去了函式呼叫的開銷,從而提高函式的
執行效率。如果執行函式體內程式碼的時間,相比於函式呼叫的開銷較大,那麼效率的收
獲會很少。另一方面,每一處行內函數的呼叫都要複製程式碼,將使程式的總程式碼量增大,
消耗更多的記憶體空間。以下情況不宜使用內聯:
(1)如果函式體內的程式碼比較長,使用內聯將導致記憶體消耗代價較高。
(2)如果函式體內出現迴圈,那麼執行函式體內程式碼的時間要比函式呼叫的開銷大。
類的建構函式和解構函式容易讓人誤解成使用內聯更有效。要當心建構函式和析構
函式可能會隱藏一些行為,如“偷偷地”執行了基類或成員物件的建構函式和解構函式。
所以不要隨便地將建構函式和解構函式的定義體放在類宣告中。
一個好的編譯器將會根據函式的定義體,自動地取消不值得的內聯(這進一步說明
了inline 不應該出現在函式的宣告中)。

 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1477815


相關文章