我们以此为例:
Class TestClass {
public:
int functionInline();
int functionComplex();
};
inline int TestClas::functionInline()
{
// a single instruction
return functionComplex();
}
int TestClas::functionComplex()
{
/* many complex
instructions
*/
}
void myFunc()
{
TestClass testVar;
testVar.functionInline();
}
假设所有的coments实际上都是单行代码或许多复杂的代码行。等效代码是(编译后):
void myFunc()
{
TestClass testVar;
// a single instruction
return functionComplex();
}
或将是:
void myFunc()
{
TestClass testVar;
// a single instruction
/* many complex
instructions
*/
}
换句话说,如果在内联函数内部调用,是否会将内联函数插入内联?
答案 0 :(得分:1)
如果编译器可以看到该函数未在其他任何地方被调用(例如,在自由函数的情况下它是static
),那么至少gcc已经将它内联了很长时间。
当然,这也假设编译器实际上可以“看到”函数的源代码 - 只有当你使用“整个程序优化”时(至少在MS和GCC编译器中可用),它是否内联函数是'在源文件中或源中包含的标头中。
显然,内联“大”函数几乎没有什么好处(因为调用的开销是总运行时的一小部分),并且如果函数被多次调用(或者“可能被称为更多)比起一次“不是static
”,编译器几乎肯定不会内联一个“大”函数。
总结:也许大函数是内联的,但很可能不是。
答案 1 :(得分:1)
请检查我为VC ++ 2010和g ++生成的汇编代码。 在这个例子中,两个编译器实际上都没有将任何函数视为内联函数。
<强>代码:强>
class TestClass {
public:
int functionInline();
int functionComplex();
};
inline int TestClass::functionInline()
{
// a single instruction
return functionComplex();
}
int TestClass::functionComplex()
{
/* many complex
instructions
*/
return 0;
}
int main(){
TestClass t;
t.functionInline();
return 0;
}
VC ++ 2010:
int main(){
01372E50 push ebp
01372E51 mov ebp,esp
01372E53 sub esp,0CCh
01372E59 push ebx
01372E5A push esi
01372E5B push edi
01372E5C lea edi,[ebp-0CCh]
01372E62 mov ecx,33h
01372E67 mov eax,0CCCCCCCCh
01372E6C rep stos dword ptr es:[edi]
TestClass t;
t.functionInline();
01372E6E lea ecx,[t]
01372E71 call TestClass::functionInline (1371677h)
return 0;
01372E76 xor eax,eax
}
Linux G ++:
main:
.LFB3:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $16, %rsp
leaq -1(%rbp), %rax
movq %rax, %rdi
call _ZN9TestClass14functionInlineEv
movl $0, %eax
leave
ret
.cfi_endproc
两行
01372E71调用TestClass :: functionInline(1371677h)
和
调用_ZN9TestClass14functionInlineEv
表示函数 functionInline 不是内联的。
现在看一下 functionInline 程序集:
inline int TestClass::functionInline()
{
01372E00 push ebp
01372E01 mov ebp,esp
01372E03 sub esp,0CCh
01372E09 push ebx
01372E0A push esi
01372E0B push edi
01372E0C push ecx
01372E0D lea edi,[ebp-0CCh]
01372E13 mov ecx,33h
01372E18 mov eax,0CCCCCCCCh
01372E1D rep stos dword ptr es:[edi]
01372E1F pop ecx
01372E20 mov dword ptr [ebp-8],ecx
// a single instruction
return functionComplex();
01372E23 mov ecx,dword ptr [this]
01372E26 call TestClass::functionComplex (1371627h)
}
因此, functionComplex 也不是内联的。
答案 2 :(得分:0)
不,不会内联。这是不可能的,因为编译器没有可用的非内联函数的主体定义可能位于另一个转换单元中。我认为正常函数是非内联函数。
答案 3 :(得分:0)
否,如果您希望内联插入复杂功能,则必须同时指定inline
关键字。
在实践中,使用__forceinline
关键字(在Windows上,在Linux上为__always_inline
)否则编译器会在有大量指令时忽略该关键字。
答案 4 :(得分:0)
首先,内联函数只是编译器的一个指令。不保证编译器会进行内联。
其次,当你将一个函数指定为内联时,它告诉编译器两件事
1)函数可能是内联的候选者。是否要内联是不能保证的 2)此功能具有内部链接。也就是说,只有在编译它的翻译单元中才能看到功能。无论函数是否实际内联,都可以保证内部链接。
在这种情况下,functionInline指定为内联,但functionComplex不指定。 functionComplex具有外部链接。编译器永远不会使用外部链接进行内联功能。
所以,对你的问题的一个简单回答是“不”正常(没有内联关键字和定义外部类的函数)函数永远不会被内联