【问题标题】:Does final keyword in c++ allow for additional compiler optimizations?c++ 中的 final 关键字是否允许额外的编译器优化?
【发布时间】:2015-03-10 06:20:45
【问题描述】:

我在考虑虚拟通话及其工作原理。我知道虚拟调用可以在编译时对值类型进行内联和硬编码。如果指针类型是声明为 final 的类(如 c# 中的密封),这是否允许编译器做同样的事情?

这在当前的编译器中做了很多,还是只是理论上/太小而无需担心?

【问题讨论】:

  • 我也很好奇。您正在寻找的术语是“去虚拟化”顺便说一句。我的猜测是标记为“final”的类型至少会使编译器的分析更容易。
  • 我相信你是对的,但最好检查生成的代码来证明这一点。做起来好像不太难。
  • 是的,如果类型(或虚函数)标记为final,您应该会看到去虚拟化。
  • C++ 编译器优化器已经“去虚拟化”了函数,如果他们能分辨出哪个函数最终被调用的话。在 C++11 之前。要求是分配在调用附近结束,无论是在代码中显式还是通过内联代码。 final 关键字不会改变这一点。

标签: c++ inheritance virtual compiler-optimization final


【解决方案1】:

是的,如果虚函数或类声明为final,则可以对调用进行去虚化。例如,给定

struct B {
  virtual void f() = 0;
};

struct D1 : B {
  virtual void f();
};

struct D2 : B {
  virtual void f() final;
};

struct D3 final : D1 {};

void f1(D1 * d) { d->f(); }
void f2(D2 * d) { d->f(); }
void f3(D3 * d) { d->f(); }

-O1 或更高级别generates 这个程序集:

f1(D1*):                              # @f1(D1*)
    movq    (%rdi), %rax
    jmpq    *(%rax)  # TAILCALL

f2(D2*):                              # @f2(D2*)
    jmp D2::f()              # TAILCALL

f3(D3*):                              # @f3(D3*)
    jmp D1::f()              # TAILCALL

注意f1 通过vtable 调用,而f2f3 中的调用是去虚拟化的。

【讨论】:

    【解决方案2】:

    我在考虑虚拟通话及其工作原理。我知道虚拟调用可以在编译时对值类型进行内联和硬编码。如果指针类型是声明为 final 的类(如 c# 中的密封),这是否允许编译器做同样的事情?

    是的,在 gcc 中对 final 成员和通过 final 类的调用将被去虚拟化,here's the code 就是这样做的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-28
      • 1970-01-01
      • 2018-12-30
      • 2021-03-19
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多