行內函數、模板函式 之於標頭檔案
本文轉自http://blog.csdn.net/cyphei/article/details/7319826
一、基本說明
C++標準中提到,一個編譯單元[translationunit]是指一個.cpp檔案以及它所include的所有.h檔案,.h檔案裡的程式碼將會被擴充套件到包含它的.cpp檔案裡,然後編譯器編譯該.cpp檔案為一個.obj檔案,後者擁有PE[PortableExecutable,即Windows可執行檔案]檔案格式,並且本身包含的就已經是二進位制碼,但是,不一定能夠執行,因為並不保證其中一定有main函式。當編譯器將一個工程裡的所有.cpp檔案以分離的方式編譯完畢後,再由聯結器(linker)進行連線成為一個.exe檔案。
模板函式
- template<typename type>
- type compare(type a,type b)
- {
- return a>b?a:b;
- }
模板函式為對近似型別的共性操作的提取,然後在編譯期間進行根據型別進行例項化(特化),因為編譯期間能夠檢查函式型別。
行內函數
- inline compare(int a,int b)
- {
- return a>b?a:b ;
- }
所以一般情況下 define定義常量、typedef定義變數、inline宣告小函式~
二、標頭檔案
1、區別&聯絡
模板函式一般宣告為inline函式,但是不是必須的。一個是呼叫點的函式展開、一個為根據型別對函式的過載。兩個功能沒有必然要黏在的理由。
模板函式是需要例項化的,而inline函式不一定需要例項化(當使用到inline函式指標時,需要例項化)。
2、標頭檔案
模板函式放在標頭檔案是因為編譯器檢查型別,編譯器看得見函式實現才能例項化模板。如果放到函式的模板的宣告和實現分開,那麼將會找不到模板實現從而後面引發連結錯誤(目前的編譯器是如此)
inline函式放在標頭檔案是因為方便統一,如果inline函式的定義和宣告是分開的,而在另外一個檔案中需要呼叫這些inline函式得時候,內聯是無法在這些呼叫函式內展開的(上面得第二個例子),只能呼叫。這樣行內函數在全域性範圍內就失去了作用
三、 轉載
轉載兩篇文章。寫的挺深入,留作備份
zz1
把inline函式定義放在標頭檔案中
http://hi.baidu.com/aihfaobh/blog/item/ffc2450899d105d962d9868c.html
兩個檔案:
main.c中得程式碼如下
#include <stdio.h>
#include "print_inline.h"
int main(int argc, char *argv[])
{
print_inline();
system("PAUSE");
return 0;
}
print_inline.h檔案中得程式碼:
#include <stdio.h>
inline void print_inline()
{
printf("This is a inlinefunction\n");
}
在預處理得時候,會把main.c檔案中得print_inline.h標頭檔案展開,在DEVC下,預處理後的檔案為main.i,(如果想要生成預處理後的檔案,需要在工程屬性裡面,為編譯器制定引數-c-save-temps
)得到如下預處理後得結果(檔案比較長,只取了最後的一部分):
# 3 "main.c" 2
# 1 "print_inline.h" 1
inline void print_inline()
{
printf("This is a inline function\n");
}
# 4 "main.c" 2
int main(int argc, char *argv[])
{
print_inline();
system("PAUSE");
return 0;
}
很明顯,在print_inline.h標頭檔案中定義得函式print_inline()在main函式中被直接展開了,相當與我們把print_inline()函式的定義放在了main.c中,這樣在編譯的時候,編譯器就可以把print_line()函式直接內聯到main函式中
但是如果我們把print_inline()函式的宣告和定義分開,即把print_inline()函式的定義放到另外一個檔案print_inline.c中,結果就不一樣了,在main.i檔案中得內容變為了
# 3 "main.c" 2
# 1 "print_inline.h" 1
inline void print_inline();
# 4 "main.c" 2
int main(int argc, char *argv[])
{
print_inline();
system("PAUSE");
return 0;
}
這個時候,print_inline()函式將無法在main函式中內聯,我們可以檢視生成得main.s彙編程式碼中包含了如下
程式碼:
LM3:
call _print_inline
其實原理很簡單,就是當用#include包含一個檔案得時候,預處理得時候會直接展開這一個檔案,如果檔案中放有某個函式的定義,事實上就相當於把該函式定義放在了這個包含這個檔案(上面得例子中得print_inline.h)的檔案(main.c)中,這樣就可以在main中將print_inline函式內聯展開
在很多時候,由於某些函式需要經常被呼叫,為了加快程式的執行速度,經常要用到inline,但是如果inline函式的定義和宣告是分開的,而在另外一個檔案中需要呼叫這些inline函式得時候,內聯是無法在這些呼叫函式內展開的(上面得第二個例子),只能呼叫。這樣行內函數在全域性範圍內就失去了作用。解決的辦法就是把行內函數得定義放在標頭檔案中,當其它檔案要呼叫這些行內函數的時候,只要包含這個標頭檔案就可以了。