如果所有派生 类 在编译时已知,final 关键字是否提供优化?

Does the final keyword provide optimization if all derived classes are known at compile time?

理论上,在 C++11 及更高版本中的虚方法声明中使用 final 关键字允许方法的内联。

This can be seen here.

但是,我怀疑在实践中,如果在编译时知道没有派生的类覆盖那个方法,编译器可以为我们插入一个final并内联这个方法.

However, putting this into compiler explorer shows that it still provides optimizations.

这是为什么?

优化方面,final 只影响编译器是否可以在编译时证明派生类型是什么。如果类型已知,则无需帮助编译器了解它。

final keyword on a virtual method declaration in C++11 and onwards allows inlining of the method

不是inlining,而是去虚拟化。

However, I suspect that in practice, if it is known at compile time that there are no derived classes overriding that method, [..]

你无法在编译时知道没有其他派生的 classes(除非 class 是 final):用户或其他 TU 可能会提供一些。它可能会在 link 完成,假设没有动态加载...

[..] the compiler can insert a final for us and inline the method However, putting this into compiler explorer shows that it still provides optimizations.

 struct A {
     virtual void f() {}
 };

struct B : public A {
     void f() final override {}
 };

struct C : public A {
     void f() override {}
 };
void foo(B& b) { b.f(); }
void bar(C& c) { c.f(); }
C::f():
        rep ret
foo(B&):
        rep ret
bar(C&):
        mov     rax, QWORD PTR [rdi]
        mov     rax, QWORD PTR [rax]
        cmp     rax, OFFSET FLAT:C::f()
        jne     .L6
        rep ret
.L6:
        jmp     rax

Why is this?

这里,当c的动态类型为C时,编译器内联调用C::frep ret): 然后它不调用 C::f,而是执行 C::f 所做的(-> 无)。

虚拟调用仍然是调用其他动态类型(jmp rax)。