0

让我们以此为例:

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();
}

假设所有评论实际上都是单行或多行复杂的代码行。等效代码将是(编译后):

void myFunc()
{
  TestClass testVar;

  // a single instruction
  return functionComplex();
}

或将是:

void myFunc()
{
  TestClass testVar;

  // a single instruction

  /* many complex
     instructions
  */
}

换句话说,如果在一个内联函数内部调用,一个普通函数是否会被内联插入?

4

5 回答 5

1

如果编译器可以看到该函数没有在其他任何地方调用(例如它是static在自由函数的情况下),那么至少 gcc 已经内联了很长时间。

当然,这也假设编译器实际上可以“看到”函数的源代码——只有当你使用“整个程序优化”(至少在 MS 和 GCC 编译器中可用)时,它才会内联函数源文件中包含的源文件或头文件。

显然,内联“大”函数几乎没有什么好处(因为进行调用的开销只占总运行时的一小部分),并且如果函数被多次调用(或“可能被多次调用”如果不是static),编译器几乎肯定不会内联“大”函数。

总之:也许大函数是内联的,但很可能不是。

于 2013-08-14T09:10:18.817 回答
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也不是内联的。

于 2013-08-14T09:38:02.793 回答
0

首先,内联函数只是编译器的一个指令。不能保证编译器会进行内联。

其次,当您将函数指定为内联时,它会告诉编译器两件事

1)函数可能是内联的候选者。不保证是否内联 2) 该函数有内部联动。也就是说,函数仅在编译它的翻译单元中可见。无论函数是否实际内联,都可以保证这种内部链接。

在您的情况下, functionInline 被指定为 inline 但 functionComplex 不是。functionComplex 具有外部链接。编译器永远不会使用外部链接进行函数内联。

因此,对您的问题的简单回答是“否”,一个普通的(没有 inline 关键字的函数并在类外部定义)函数永远不会被内联

于 2013-08-14T09:08:41.693 回答
0

不,它不会被内联。这是不可能的,因为编译器没有可用的非内联函数的主体定义,该函数可能位于另一个翻译单元中。我想普通函数是一个非内联函数。

于 2013-08-14T09:04:00.310 回答
0

,如果您想内联插入复杂的函数,您也必须指定inline关键字。
在实践中,使用__forceinline关键字(在 Windows 上,__always_inline在 linux 上),否则如果有很多指令,编译器将忽略该关键字。

于 2013-08-14T09:07:30.543 回答