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