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