这是对您的示例的快速测试(使用MyA::foo()
简单地返回的实现42
)。所有这些测试都是针对 32 位目标进行的 - 64 位目标可能会出现不同的结果。还值得注意的是,使用-flto
选项(GCC)或/GL
选项 (MSVC) 可实现全面优化 - 无论在何处MyB::foo()
被调用,它只是被替换为42
.
使用 GCC(MinGW 4.5.1):
gcc -g -O3 -o test.exe myb.cpp mya.cpp test.cpp
对 MyB::foo() 的调用没有被优化掉。MyB::foo()
本身稍微优化为:
Dump of assembler code for function MyB::foo() const:
0x00401350 <+0>: push %ebp
0x00401351 <+1>: mov %esp,%ebp
0x00401353 <+3>: sub $0x8,%esp
=> 0x00401356 <+6>: leave
0x00401357 <+7>: jmp 0x401360 <MyA::foo() const>
这是条目序言保留在原处,但立即撤消(leave
指令)并且代码跳转到 MyA::foo() 来完成真正的工作。然而,这是一个优化compiler(不是链接器)正在做,因为它意识到MyB::foo()
只是返回任何内容MyA::foo()
返回。我不知道为什么要留下序言。
MSVC 16(来自 VS 2010)的处理方式略有不同:
MyB::foo()
最终以两次跳跃结束——一次跳跃到某种“重击”:
0:000> u myb!MyB::foo
myb!MyB::foo:
001a1030 e9d0ffffff jmp myb!ILT+0(?fooMyAQBEHXZ) (001a1005)
重击声直接跳到了MyA::foo()
:
myb!ILT+0(?fooMyAQBEHXZ):
001a1005 e936000000 jmp myb!MyA::foo (001a1040)
再说一遍 - 这很大程度上(全部?)由编译器执行,因为如果您查看链接之前生成的目标代码,MyB::foo()
被编译为普通跳转MyA::foo()
.
因此,归结为所有这些 - 看起来在没有显式调用 LTO/LTCG 的情况下,今天的链接器不愿意/无法执行删除调用的优化MyB::foo()
总的来说,即使MyB::foo()
是一个简单的跳转MyA::foo()
.
所以我想如果你想要链接时间优化,请使用-flto
(对于海湾合作委员会)或/GL
(对于 MSVC 编译器)和/LTCG
(对于 MSVC 链接器)选项。