我不断听说该inline关键字不再用作现代编译器的提示,而是用于避免多源项目中的多重定义错误。
但今天我遇到了一个编译器遵守关键字的例子。
没有inline关键字的话,代码如下
#include <iostream>
using namespace std;
void func(const int x){
if(x > 3)
cout << "HAHA\n";
else
cout << "KKK\n";
}
int main(){
func(5);
}
Run Code Online (Sandbox Code Playgroud)
使用命令g++ -O3 -S a.cpp,生成未内联的汇编代码func。
但是,如果我在 的定义前面添加 inline 关键字func,则func会内联到 中main。
生成的汇编代码部分是
.LC0:
.string "HAHA\n"
.LC1:
.string "KKK\n"
.text
.p2align 4,,15
.globl _Z4funci
.type _Z4funci, @function
_Z4funci:
.LFB975:
.cfi_startproc
cmpl $3, %edi
jg .L6
movl $4, %edx
movl $.LC1, %esi
movl $_ZSt4cout, %edi
jmp _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
.p2align 4,,10
.p2align 3
main:
.LFB976:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $5, %edi
call _Z4funci
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
Run Code Online (Sandbox Code Playgroud)
我的编译器是 gcc 4.8.1 / x86-64。
我怀疑该函数可以在链接过程中内联,但我不确定会发生这种情况,如果是这样,我怎么知道?
我的问题是为什么这个代码片段似乎与现代指南相矛盾,例如 何时应该为函数/方法编写关键字“内联”?
该inline关键字有多种作用。其中之一是向编译器暗示您希望内联该函数 - 然而,这并不意味着编译器必须内联它[几个编译器中有一个扩展说“无论如何,如果有的话,内联这个”可能”,例如 MS__forceinline和 gcc __attribute__(always_inline)]。
如果函数inline是内联的,关键字还允许您拥有具有相同名称的函数的多个实例,而不会出现“同一函数的多个定义”的错误。[但每次函数必须是相同的源]。
在这种情况下,我有点惊讶地看到编译器 NOT inline func。然而,添加statictofunc也会使其内联。很明显,编译器基于这样一个事实来决定这一点:“其他一些函数也可能正在使用func,所以我们无论如何都需要一个副本,并且内联它并没有太多好处。事实上,如果你将一个函数设为静态,那么它就是仅调用一次,即使函数非常大,gcc/g++ 几乎肯定会内联它。
如果您希望编译器内联某些内容,添加inline. 然而,在许多情况下,编译器都会做出适当的选择。例如,如果我将代码更改为:
const char* func(const int x){
if(x > 3)
return "HAHA\n";
else
return "KKK\n";
}
int main(){
cout << func(5);
}
Run Code Online (Sandbox Code Playgroud)
它确实内联了return "HAHA\n";剩下的部分func。
编译器决定内联或不内联的逻辑很复杂,其中一部分是“我们获得了多少,以及它占用了多少代码空间” - 调用的开销operator<<(ostream& ,const char *)对于在这种情况下是内联的。不幸的是,理解编译器为什么做出某个决定并不总是容易的......
| 归档时间: |
|
| 查看次数: |
2887 次 |
| 最近记录: |