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

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 に答える
1

関数が他の場所で呼び出されていないことをコンパイラが確認できる場合 (たとえばstatic、フリー関数の場合)、少なくとも gcc は長い間インライン化されています。

もちろん、これはコンパイラが関数のソースコードを実際に「見る」ことができることも前提としています - 「プログラム全体の最適化」(少なくともMSおよびGCCコンパイラで利用可能)を使用する場合にのみ、どちらにもない関数をインライン化しますソース ファイルまたはソースに含まれるヘッダー。

明らかに、「大きな」関数をインライン化してもほとんどメリットがありません (呼び出しを行うオーバーヘッドは実行時間全体のごく一部であるため)、関数が複数回呼び出された場合 (または「複数回呼び出される可能性がある」場合)でないことによりstatic)、コンパイラはほぼ確実に「大きな」関数をインライン化しません。

要約すると、大規模な関数はインラインである可能性がありますが、そうではない可能性が非常に高くなります。

于 2013-08-14T09:10:18.817 に答える
0

まず、インライン関数はコンパイラへの単なる指示です。コンパイラがインライン化を行うことは保証されていません。

次に、関数をインラインとして指定すると、コンパイラに 2 つのことが伝えられます。

1) 関数はインライン化の候補になる可能性があります。インライン化されるかどうかは保証されません。 2) この関数には内部リンケージがあります。つまり、関数はコンパイルされた翻訳単位でのみ表示されます。この内部リンケージは、関数が実際にインライン化されているかどうかに関係なく保証されています。

あなたの場合、 functionInline はインラインとして指定されていますが、 functionComplex はそうではありません。functionComplex には外部リンケージがあります。コンパイラは、外部リンケージを使用して関数のインライン化を行うことはありません。

したがって、あなたの質問に対する簡単な答えは「いいえ」です。通常の(インラインキーワードのない関数とクラス外で定義された関数)関数は決してインライン化されません

于 2013-08-14T09:08:41.693 に答える
0

いいえinline、複雑な関数をインラインで挿入する場合は、キーワードも指定する必要があります。
実際には、__forceinlineキーワード (Windows、__always_inlineLinux) を使用します。そうしないと、多くの命令がある場合、コンパイラはキーワードを無視します。

于 2013-08-14T09:07:30.543 に答える