c ++与调用相关的内联函数定义位置

时间:2015-11-18 22:24:12

标签: c++ inline

在c ++中,考虑到单个编译单元,函数的定义是否必须高于对它的调用才能被内联,或者它是否应该定义在编译单元的某个位置? / p>

换句话说,之间有什么区别:

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()中内联?

由于

2 个答案:

答案 0 :(得分:2)

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

“这种优化发生的”种类的问题通常是编译器相关的,因此最好通过询问编译器来解答,例如:

# 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!\00"

; 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),至少对于我正在使用的编译器而言。

答案 1 :(得分:0)

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