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 调用,而f2
和f3
中的调用是去虚拟化的。
【讨论】:
【参考方案2】:我在考虑虚拟通话及其工作原理。我知道虚拟调用可以在编译时对值类型进行内联和硬编码。如果指针类型是声明为 final 的类(如 c# 中的密封),这是否允许编译器做同样的事情?
是的,在 gcc
中对 final 成员和通过 final 类的调用将被去虚拟化,here's the code 就是这样做的。
【讨论】:
以上是关于c++ 中的 final 关键字是不是允许额外的编译器优化?的主要内容,如果未能解决你的问题,请参考以下文章