C++编译器:在同一模块中定义的非内联函数的内联用法



T.hpp

class T
{
int _i;
public:
int get() const;
int some_fun();
};

T.cpp

#include "T.hpp"
int T::get() const
{ return _i; }
int T::some_fun()
{
// noise
int i = get(); // (1)
// noise
}

get()是一个非内联函数,但它与some_fun在同一模块中定义。既然编译器可以在some_fun的上下文中看到get的定义,那么编译器(至少在优化的构建中)是否应用了在(1)行仅用_i替换get()的优化?

如果我没有错的话,我认为除了模板之外,编译器只进行一次性解析。如果get是在some_fun之后定义的呢?

好的,我自己回答了。我以为我不会讲集会,但这并不难。

代码:

class T
{
int _i = 5;
public:
int get() const;
int some_fun();
};
int T::get() const { return _i; }
int T::some_fun()
{
int i = get();
return i;
}
int main()
{
T o;
return o.some_fun();
}

未优化的汇编输出(使用godbolt.org)。很多东西,但你可以看到显式的calls:

T::get() const:
push    rbp
mov     rbp, rsp
mov     QWORD PTR [rbp-8], rdi
mov     rax, QWORD PTR [rbp-8]
mov     eax, DWORD PTR [rax]
pop     rbp
ret
T::some_fun():
push    rbp
mov     rbp, rsp
sub     rsp, 24
mov     QWORD PTR [rbp-24], rdi
mov     rax, QWORD PTR [rbp-24]
mov     rdi, rax
call    T::get() const              // !!!!
mov     DWORD PTR [rbp-4], eax
mov     eax, DWORD PTR [rbp-4]
leave
ret
main:
push    rbp
mov     rbp, rsp
sub     rsp, 16
mov     DWORD PTR [rbp-4], 5
lea     rax, [rbp-4]
mov     rdi, rax
call    T::some_fun()          // !!!!
nop
leave
ret

优化输出(-O3):

T::get() const:
mov     eax, DWORD PTR [rdi]
ret
T::some_fun():
mov     eax, DWORD PTR [rdi]
ret
main:
mov     eax, 5
ret

这里,some_fun内联了对get的调用(call指令已被删除,其定义与现在的get相同),但仍然定义了get函数。

main更进一步,对some_fun的调用进行了内联替换,然后意识到o没有更改,此时它仍然保留其默认值5,因此main直接返回5,甚至不创建o

最新更新