C++ FAQ閱讀筆記[3]--內聯函數

W[9.1] 內聯函數是幹嘛的?
內聯函數是將被插入到調用者代碼流中的函數,就像一個#define的宏一樣,內聯函數通過避免調用自己和(特別是)通過編譯在調用過程中優化調用過程(過程整合)來達到提升性能的效果.

[9.2] 內聯函數是如果保證安全和速度的平衡性的?
在C中,你可以通過在結構體裏面放置一個void*來達到"封裝的結構體",這種情況下,void*指向結構體中用戶不知道的實際數據。這樣結構體的用戶就不知道如何解釋用void*指向的內容,但是訪問這些函數的時候就會從void*型自動轉換爲相應的合適的類型。這就給出了一種形式的封裝。

不幸的是它失去了類型的安全性,它也在強制函數調用的時候要訪問結構體中每個角落的數據(如果你允許對結構體進行直接的訪問的話,任何人都可以訪問它們,因爲他們有必要知道他們如何解析用void*指向的東西,這個會讓改變數據結構的時候變得更加困難了.

C++類允許函數調用擴展內聯.這就可以讓你安全地進行封裝,而且保證了快速的直接的訪問.此外,這些內聯函數的參數類型是由編譯器來進行檢查的,這是對於C中的#define宏的一個改進.

[9.3] 我爲什麼要用內聯函數呢?而不是用原來好好的#define宏?

因爲#define宏在四個方面是非常糟糕的(這裏的內容沒有找到,比較遺憾)

不像#define宏,內聯函數可以避免聲名狼籍的宏錯誤因爲內聯函數總是對每個參數精確匹配一次。換言之,調用內聯函數在語義上只是像調用了一個正則表達式,只是要更快一些:

//一個返回i絕對值的宏
#define unsafe(i)  ( (i) >=0 ? (i) : -(i) )

//一個返回i的絕對值的內聯函數
inline int safe(int i)
{
 return i>=0?i:-i;
}

int f();

void userCode(int x)
{
 int ans;

 ans=unsafe(x++);
 ans=unsafe(f());

 ans=safe(x++);
 ans=safe(f());
}


與宏不一樣的是,參數的類型是會被檢查的,不必要的會話會被正確的處理。

宏對你的程序的健康是不利的,除非不得以,否則不要用它們!

[9.4] 你怎麼讓編譯器識別一個非成員函數的內聯函數?
當你申明一個內聯函數的時候,它看起來就像是一個普通的函數:
void f(int i,char c)
但是當你定義一個內聯的函數,你把函數的定義加上inline關鍵字,當你所以下的定義放入頭文件之後:

inline
void f(int i,char c)
{
 //...
}
注意:把一個函數的定義放到一個頭文件裏面是一個規則性的東西。除非函數只是在一個單獨的cpp文件中調用到了。特別的,如果你把內聯函數放在一個cpp文件裏面,而你從其他的cpp文件裏面調用它,你會在連接器得到一個"unresolved external"錯誤。

[9.5] 你怎麼讓編譯器識別一個內聯的成員函數?
當你定義一個成員函數的時候,它看起來就像是一個普通的成員函數:

class Fred  {
public: 
 void f(int i,char c);
};

但是如果你定義一個內聯的成員函數的時候,你就得在函數定義前使用inline關鍵字,並且把這個定義放到一個頭文件中,
inlune
void Fred::f(int i,char c)
{
 //...
}

注意:把一個函數的定義放到一個頭文件裏面是一個規則性的東西。除非函數只是在一個單獨的cpp文件中調用到了。特別的,如果你把內聯函數放在一個cpp文件裏面,而你從其他的cpp文件裏面調用它,你會在連接器得到一個"unresolved external"錯誤。

[9.6] 是不是有另外一種方法讓編譯器識別到一個內聯的成員函數?
是的!在類體內定義一個成員函數的時候就相當於把它申明爲一個內聯函數:

class Fred  {
public:
 void f(int i,char c)
 {
  //...
 }
};

儘管這對於寫這個類的人來說更加簡單一些,但是這個對於所有的閱讀者來說就變得更加困難了,因爲它混了什麼是一個類與這個類怎麼實現它兩個問題。因爲這個混淆的存在,我們通常用inline關鍵字在類的外面定義成員函數。這個認識就有以下的意義了:在一個面向代碼重用的世界裏,有很多人會使用你的類,但是隻有一個人來編寫它(你自己),這樣你就應該做一些能讓更多的人受益的事,而不讓極少數人受益.

[9.7] 內聯函數會一定讓你的程序性能更好嗎?
不是的。

注意內聯函數的過度應用會造成代碼的膨腫,這個會讓分頁平臺環境的性能降低。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章