Reputation: 1901
In theory, using the final
keyword on a virtual method declaration in C++11 and onwards allows inlining of the method.
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
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
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