优化虚拟表查找

时间:2012-09-13 16:57:46

标签: c++ compilation compiler-optimization

使用下面的代码,编译器是否可以告诉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查找?

2 个答案:

答案 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%的申请时间是一个地方,问题得到解答。 “哦,但它效率低下”,这是最常见的答案,导致无法维护的代码很少优化实际上效率低下的代码。