c++ 中的 final 关键字是不是允许额外的编译器优化?

Posted

技术标签:

【中文标题】c++ 中的 final 关键字是不是允许额外的编译器优化?【英文标题】: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 关键字不会改变这一点。 How does the compiler benefit from C++'s new final keyword?的可能重复 【参考方案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 就是这样做的。

【讨论】:

以上是关于c++ 中的 final 关键字是不是允许额外的编译器优化?的主要内容,如果未能解决你的问题,请参考以下文章

java中的 final关键字

关于Java中的final关键字

C++多态知识点深入了解

final .....finally ...... 和Finalize ......区别

Java中的final

Java面试题1--关键字