c++ 内联函数定义相对于调用的位置

c++ inline function definition position in relation to call

在 c++ 中,考虑单个编译单元,函数的定义是否必须高于对其的调用才能被内联,或者定义位于编译单元中的某处是否足够?

换句话说,有什么区别:

class A {
public:
    void f();
};

class B {
    A a;
public:
    void g();
};

inline void A::f() {
    printf("Func'ing A!\n");
}

void B::g() {
    //...
    a.f();
}

class A {
public:
    void f();
};

class B {
    A a;
public:
    void g();
};

void B::g() {
    //...
    a.f();
}

inline void A::f() {
    printf("Func'ing A!\n");
}

关于 A::f() 内联 B::g() ?

谢谢

inline 是给编译器的提示,编译器可以选择是否实际内联。 您可能想看看 this answer

我认为这是一个合理的问题。在 C++ 中,有几种情况文件中的文本顺序很重要。幸运的是,这不是其中之一 - 您的两个代码示例是等效的。如 Claudio 所述,在源代码中写入 'inline' 没有任何区别。

各种 "does this optimisation happen" 的问题通常取决于编译器,因此最好通过询问编译器来回答,例如:

# clang++ -c first.cpp -O3 -S -emit-llvm -o first.ll

; ModuleID = 'first.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

%class.B = type { %class.A }
%class.A = type { i8 }

@str = private unnamed_addr constant [12 x i8] c"Func'ing A![=10=]"

; Function Attrs: nounwind uwtable
define void @_ZN1B1gEv(%class.B* nocapture readnone %this) #0 align 2 {
  %puts.i = tail call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @str, i64 0, i64 0)) #1
  ret void
}

; Function Attrs: nounwind
declare i32 @puts(i8* nocapture readonly) #1

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }

!llvm.ident = !{!0}

!0 = metadata !{metadata !"Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)"}

或者,如果您更喜欢 x86-64,

# clang++ -c first.cpp -O3 -S -o first.s
    .text
    .file   "first.cpp"
    .globl  _ZN1B1gEv
    .align  16, 0x90
    .type   _ZN1B1gEv,@function
_ZN1B1gEv:                              # @_ZN1B1gEv
    .cfi_startproc
# BB#0:
    movl    $.Lstr, %edi
    jmp puts                    # TAILCALL
.Ltmp0:
    .size   _ZN1B1gEv, .Ltmp0-_ZN1B1gEv
    .cfi_endproc

    .type   .Lstr,@object           # @str
    .section    .rodata.str1.1,"aMS",@progbits,1
.Lstr:
    .asciz  "Func'ing A!"
    .size   .Lstr, 12


    .ident  "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)"
    .section    ".note.GNU-stack","",@progbits

这两个片段使用 clang 3.5 编译为完全相同的中间表示 - 使用 diff 工具最容易验证 - 因此我们可以确信源中的相对位置没有区别。

这实际上也是没有优化的情况(使用-O0),至少对于我正在使用的编译器而言。