3

什麼是內聯函數之間,然後主像這樣的區別:內聯函數原型VS定期申報VS原型

inline double cube(double side) 
{ 
    return side * side * side; 
} 

int main() 
{ 
    cube(5); 
} 

VS只需定期聲明一個函數,如:

double cube(double side) 
{ 
    return side * side * side; 
} 

int main() 
{ 
    cube(5); 
} 

VS函數原型?

double cube(double); 

int main() 
{ 
    cube(5); 
} 

double cube(double side) 
{ 
    return side * side * side; 
} 
+3

你是不是指'cube(5);'? – log0

+0

我想是的。 – log0

+0

[C++內聯函數?](http://stackoverflow.com/questions/5971736/c-inline-function)的可能重複 - 也參見。 [這是我的答案](http://stackoverflow.com/questions/7738888/what-is-concept-of-inline-function-and-how-it-is-differ-from-macro/7739024#7739024)。 –

回答

1

性能方面,它們都是相同的,因爲inline只是編譯器的提示。如果使用聲明/定義的分離,並且定義位於不同的翻譯單元上,那麼編譯器將很難將其內聯(但有些實現可以這樣做)。

與函數inline的區別在於,如果鏈接器多次看到函數的相同內聯定義,則鏈接器不會投訴。

6

一個inline函數可以定義在多個翻譯單元(cpp文件+包含)中,並且是編譯器對內聯函數的提示。它通常放在一個頭文件中,這會增加編譯時間,但可以通過導致更快的代碼。它還允許從許多編譯單元使用該功能。

//cube.h 
inline double cube(double side) 
{ 
    return side * side * side; 
} 

//cube.cpp 
int main() 
{ 
    cube(5); 
} 

定期定義它是正常的方法,它通常在cpp文件中定義,並且鏈接到它。它不容易從其他編譯單元中使用。

//cube.cpp 
double cube(double side) 
{ 
    return side * side * side; 
} 

int main() 
{ 
    cube(5); 
} 

原型允許您告訴編譯器鏈接時會存在一個函數,即使它現在還不存在。這允許main調用該函數,即使它尚不存在。通常情況下,原型是在標題中,所以其他編譯單元可以調用該函數,而不需要自己定義它。這是最快的編譯時間,並且該函數很容易從其他編譯單元中使用。

//cube.h 
double cube(double); 

//cube.cpp 
int main() 
{ 
    cube(5); 
} 

double cube(double side) 
{ 
    return side * side * side; 
} 
+1

* ...可以在單個編譯單元(cpp文件+包含)中定義多次* - 是否指__different__編譯單元? – anatolyg

+0

不允許,'inline'被允許違反ODR,就像模板一樣。否則,很難在頭文件中添加內聯,並且如果它不在頭文件中,愚蠢的編譯器不能內聯它! –

+0

優秀和高度可理解的解釋,先生/女士。非常感謝! – iggy2012

0

當你聲明一個內聯函數時,編譯器試圖通過或多或少地將函數體複製到被調用的位置來加速代碼。這只是一個建議,如果可能的話,是由編譯器決定的。

我不確定在第三個例子中會發生什麼。我想這將取決於正在使用的工具鏈。

+0

最後一個只是main()之前的函數原型。他們似乎都以同樣的方式工作,但我似乎不明白有什麼區別。 – iggy2012

1

3程序編譯與g++ -S -O3 $file.cc完全一樣。 除了第二個示例,其中double cube(double side)的定義仍然以非內聯格式存在,儘管內嵌在int main()中。

_main: 
pushl %ebp 
movl $16, %eax 
movl %esp, %ebp 
subl $8, %esp 
andl $-16, %esp 
call __alloca 
call ___main 
leave 
xorl %eax, %eax 
ret 
+0

您指出的差異是實現的細節,有些編譯器會始終生成所有函數,即使它是實際內聯的,因爲您可以獲取「內聯」函數的地址,編譯器可能不知道處理函數,如果稍後在相同的TU中請求該函數的地址。 –

+0

@大衛正是。 – log0