【问题标题】:Devirtualizing a non-final method非最终方法的虚拟化
【发布时间】:2015-12-19 15:41:22
【问题描述】:

假设我有如下的类设置:

class A {
  public:
    virtual void foo() { printf("default implementation\n"); }
};

class B : public A {
  public:
    void foo() override { printf("B implementation\n"); }
};

class  C : public B {
  public:
    inline void foo() final { A::foo(); }
};

int main(int argc, char **argv) {
  auto c = new C();
  c->foo();
}

一般来说,对c->foo() 的调用可以去虚拟化并内联到printf("default implementation") 调用吗?这是否有保证,例如在 gcc 中?我的直觉是 A::foo() 是非虚拟的,因为该类是明确指定的,因此 printf 将始终被内联。

【问题讨论】:

    标签: c++ gcc g++ c++14


    【解决方案1】:

    您是在询问优化问题,因此通常我们必须选择一个编译器并尝试一下。我们可以查看汇编输出以确定编译器是否按照您想要的方式进行优化。

    Let's try GCC 5.2:

    .LC0:
        .string "B implementation"
    B::foo():
        movl    $.LC0, %edi
        jmp puts
    .LC2:
        .string "default implementation"
    A::foo():
        movl    $.LC2, %edi
        jmp puts
    C::foo():
        movl    $.LC2, %edi
        jmp puts
    main:
        subq    $8, %rsp
        movl    $8, %edi
        call    operator new(unsigned long)
        movl    $.LC2, %edi
        call    puts
        xorl    %eax, %eax
        addq    $8, %rsp
        ret
    

    And let's try out Clang 3.6:

    main:                                   # @main
        pushq   %rax
        movl    $.Lstr, %edi
        callq   puts
        xorl    %eax, %eax
        popq    %rdx
        retq
    
    .Lstr:
        .asciz  "default implementation"
    

    在这两种情况下,您都可以非常清楚地看到所有虚函数都已内联。

    “这是否有保证,例如在 gcc 中?”

    如果编译器对对象的实际类型有信心,那么我怀疑这种优化总会发生。不过,我没有任何证据支持这一说法。

    【讨论】:

      猜你喜欢
      • 2013-05-01
      • 1970-01-01
      • 2015-06-13
      • 2012-06-19
      • 2012-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多