与包含复杂函数的内联
Inline with containing complex function
让我们举个例子:
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();
}
假设所有的coment实际上都是单行或多行复杂代码的代码行。等效代码为(编译后):
void myFunc()
{
TestClass testVar;
// a single instruction
return functionComplex();
}
或者是:
void myFunc()
{
TestClass testVar;
// a single instruction
/* many complex
instructions
*/
}
换句话说,如果在内联函数内部调用一个普通函数,它是否会内联插入?
如果编译器可以看到函数在其他地方没有被调用(例如,在自由函数的情况下,它是static
),那么至少gcc已经内联了它很长一段时间。
当然,这也假设编译器实际上可以"看到"函数的源代码——只有当你使用"整个程序优化"(至少在MS和GCC编译器中可用)时,它才能内联不在源文件或源中包含的头文件中的函数。
显然,内联一个"大"函数没有什么好处(因为进行调用的开销在整个运行时中只占很小的一部分),如果该函数被多次调用(或者由于不是static
而"可能被多次调用"),编译器几乎肯定不会内联一个"大"函数。
总之:也许大型函数是内联的,但很可能不是。
请检查我为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)
和
调用_ZN9TestClass14函数InlineEv
指示函数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)
}
因此,函数Complex也不是内联的。
否,如果您希望以内联方式插入复杂函数,则还必须指定inline
关键字
在实践中,使用__forceinline
关键字(在windows上,__always_inline
在linux上),否则如果有很多指令,编译器将忽略该关键字。
首先,内联函数只是编译器的一个指令。不能保证编译器会执行内联。
其次,当您指定一个函数为内联时,它会告诉编译器两件事
1) 函数可能是内联的候选者。不能保证它是否会被内联2) 此功能具有内部链接。也就是说,函数只有在编译的翻译单元中才可见。无论函数是否实际内联,都可以保证这种内部链接。
在您的情况下,functionInline被指定为inline,但functionComplex不是。functionComplex具有外部链接。编译器永远不会对具有外部链接的函数进行内联。
因此,您的问题的简单答案是"否"。一个正常的(没有内联关键字并在类外定义的函数)函数永远不会内联
- 函数何时会在c++中包含stack_Unwind_Resume调用
- g++ 说函数不存在,即使包含正确的标头
- 当调用switch语句中的函数时(即使函数不包含循环),似乎是永不结束的循环的问题
- 如果基类包含双指针成员,则派生类的构造函数
- 一个函数,用于查找字符串1包含字符串2 c++的次数
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 复制包含C++所有元素的对象!(构造函数和赋值,最佳实践?
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 如果 x.h 仅由函数声明组成,为什么有必要在 x 中包含 x.h.cpp
- 如果函数包含静态变量,为什么编译器不执行内联?
- 为什么宏__STL_FUNCTION_MPL_PARTIAL_ORDER应该将模板函数包含在std_pair.h中
- 如果函数包含在命名空间中,则"go to beginning of the function"不起作用 (C++)
- 创建自己所需的函数比为某个函数包含整个库更可取吗
- cv::meanShift函数包含什么
- 是否应将析构函数包含在使用自动存储的指针中
- 函数包含未命名参数
- 如何使我的resize函数包含前一个向量的元素?
- 将头文件中的特定函数包含到c++代码中
- c++类的析构函数包含ptr到对象的数组