I am just wondering if most compilers can do the following optimization
class A
{
virtual void f() { m = 5; }
void g() { f(); }
int m;
};
f()
is a virtual function and thus is not inline. However, can the compiler optimize g()
for calling f()
as inline since the definition of f()
is short and available?
can the compiler optimize g() for calling f() as inline since the definition of f() is short and available?
That's pretty convoluted. g()
can be inlined, such that calling A::g()
generates the same optimised code as calling A::f()
. If you derive from A
, g()
can still be inlined regardless of whether it's called on a variable for which runtime type is known at compile time or via an A*
or A&
to an object of unknown runtime type.
But, that's got nothing to do with f()
being "short and available" - so I'm guessing your intent is to ask whether f()
itself can be inlined: sometimes, specifically - when the runtime type is known at compile time f()
itself may be inlined too.
struct B : A { void f() { ... } }
B b;
b.g(); // g() and B::f() may be inlined
A* p = &b;
p->g(); // g() and B::f() may be inlined (latter iff optimiser tracks p addressing a B)
p = opaque_factory(); // definition not known to compiler
p->g(); // equivalent to p->f();, g() inline, f() dispatched virtually / not inline.
void x(A* p) { p->g(); } // g() may be inlined
x(p); // iff x is inlined, g() and B::f() may be too - per p->g() call above
// iff x is out-of-line, and compiler doesn't do full-program analysis and find
// it's only ever called for a specific runtime type (unlikely if not a
// single-translation-unit program), then dispatch to f() can not be inlined
// and must be virtual
By not just declaring but actually defining g()
(i.e. providing implementation) in the class definition, you implicitly tell the compiler g()
can be inline.
The lack of overhead of g()
is one reason the Non Virtual Interface idiom (where the virtual functions are made non-public and accessed via non-virtual public functions, allowing easy later customisation of the base class wrapper function to add instrumentation/logging etc. if needed) is attractive - there's no performance cost in optimised builds while extra functionality's not (yet) been added.
I don't think they can. Here's why:
class B : public A
{
virtual void f() {}
}
B b;
b.g(); // This must result in B::f() getting called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With