使用下面的代码,编译器是否可以告诉a
实际上是B
的实例并优化掉虚拟表查找?
#include <iostream>
class A
{
public:
virtual void f()
{
std::cout << "A::f()" << std::endl;
}
};
class B : public A
{
public:
void f()
{
std::cout << "B::f()" << std::endl;
}
};
int main()
{
B b;
A* a = &b;
a->f();
return 0;
}
在Jonthan Seng和reima的答案之后的其他问题:如果使用gcc,是否有必要使用任何标志来强制它来优化vtable查找?
答案 0 :(得分:7)
Clang可以轻松进行此优化,甚至可以内联函数调用。这可以从生成的程序集中看出:
Dump of assembler code for function main():
0x0000000000400500 <+0>: push %rbp
0x0000000000400501 <+1>: mov %rsp,%rbp
0x0000000000400504 <+4>: mov $0x40060c,%edi
0x0000000000400509 <+9>: xor %al,%al
0x000000000040050b <+11>: callq 0x4003f0 <printf@plt>
0x0000000000400510 <+16>: xor %eax,%eax
0x0000000000400512 <+18>: pop %rbp
0x0000000000400513 <+19>: retq
我冒昧地通过对std::cout << …
的等效调用替换printf
,因为这大大减少了反汇编中的混乱。
GCC 4.6还可以推断出不需要vtable查找,但不能内联:
Dump of assembler code for function main():
0x0000000000400560 <+0>: sub $0x18,%rsp
0x0000000000400564 <+4>: mov %rsp,%rdi
0x0000000000400567 <+7>: movq $0x4007c0,(%rsp)
0x000000000040056f <+15>: callq 0x400680 <B::f()>
0x0000000000400574 <+20>: xor %eax,%eax
0x0000000000400576 <+22>: add $0x18,%rsp
0x000000000040057a <+26>: retq
答案 1 :(得分:-2)
也许它可以 - 这将取决于编译器的智能和优化要求。
但是,这是一个电话。你为什么关心优化这一个电话?并且,如果你关心,为什么不只是为这一个电话获得正确的类型?
关于优化的所有问题的第一个答案是,“为什么需要对其进行优化?”有一个性能工具报告说50%的申请时间是一个地方,问题得到解答。 “哦,但它效率低下”,这是最常见的答案,导致无法维护的代码很少优化实际上效率低下的代码。