Omegastick
Omegastick

Reputation: 1901

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

In theory, using the final keyword on a virtual method declaration in C++11 and onwards allows inlining of the method.

This can be seen here.

However, I suspect that in practice, if it is known at compile time that there are no derived classes overriding that method, the compiler can insert a final for us and inline the method.

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

Why is this?

Upvotes: 0

Views: 86

Answers (2)

Jarod42
Jarod42

Reputation: 217235

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

Not inlining, but de-virtualization.

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

You cannot know at compile time that there are no other derived classes (unless class is final): user or other TU might provide some. it might potentially be done at link, supposing no dynamic loading...

[..] 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?

Here, compiler inlines call of C::f (rep ret) for the case when dynamic type of c is C: then instead of calling C::f, it does what C::f does (-> nothing).

virtual call is still call for other dynamic type (jmp rax).

Upvotes: 2

eerorika
eerorika

Reputation: 238321

Optimisation wise, final only affects whether the compiler can prove what the derived type is at compile time. If the type is known then there is no need to help the compiler to know it.

Upvotes: 0

Related Questions