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)。很多东西,但你可以看到显式的call
s:
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
。