single virtual inheritance compiler optimization in c++? - c++

If I have this situation in C++ project:
1 base class 'Base' containing only pure virtual functions
1 class 'Derived', which is the only class which inherits (public) from 'Base'
Will the compiler generate a VTABLE?
It seems there would be no need because the project only contains 1 class to which a Base* pointer could possibly point (Derived), so this could be resolved compile time for all cases.
This is interesting if you want to do dependency injection for unit testing but don't want to incur the VTABLE lookup costs in production code.

I don't have hard data, but I have good reasons to say no, it won't turn virtual calls into static ones.
Usually, the compiler only sees a single compilation unit. It cannot know there's only a single subclass, because five months later you may write another subclass, compile it, get some ancient object files from the backup and link them all together.
While link-time optimizations do see the whole picture, they usually work on a far lower-level representation of the program. Such representation allow e.g. inlining of static calls, but don't represent inheritance information (except perhaps as optional metadata) and already have the virtual calls and vtables spelt out explicitly. I know this is the case for Clang and IIRC gcc's whole-program optimizations also work on some low-level IR (GIMPLE?).
Also note that with dynamic loading, you can still add more subclasses long after compilation and LTO. You may not need it, but if I was a compiler writer, I'd be weary of adding an optimization that allows people royally breaking virtual calls in very specific, hard-to-track-down circumstances.
It's rarely worth the trouble - if you don't need virtual calls (e.g. because you know you won't need any more subclasses), don't make stuff virtual. Review your design. If you need some polymorphism but not the full power of virtual, the curiously recurring template pattern may help.

The compiler doesn't have to use a vtable based implementation of virtual function dispatch at all so the answer to your question will be specific to the implementation that you are using.

The vtable is usually not only used for virtual functions, but it is also used to identify the class type when you do some dynamic_cast or when the program accesses the type_info for the class.
If the compiler detects that no virtual functions ever need a dynamic dispatch and none of the other features are used, it just could remove the vtable pointer as an optimization.
Obviously the compiler writer hasn't found it worth the trouble of doing this. Probably because it wouldn't be used very often.

Related

Compile time elimination of virtual tables?

Assuming i have this hierarchy :
class Super
{
public:
virtual void bar();
};
class Sub : public Super
{
public:
virtual void bar() override;
};
is there a way for me to avoid vtables despite using the virtual key word? (curiosity) i have read something about a compiler optimization that eliminates vtables when the object is known during compile time, I'm not really sure, been digging around google for a while, but could't find any answers, so does it mean these?
Sub sb;
sb.bar(); //avoids vtable?
Super& sr = sb;
sr.bar(); //avoids vtable?
Super* srp = &sb;
srp->bar(); //avoids vtable?
One of the gcc developers has a whole series of blog posts about devirtualization. I think he is also active on SO, so there may be a chance that he responses.
However, devirtualization deals mostly with eliminating virtual dispatch by analyzing the program flow and possible types. I don't think it removes the virtual table in general, but there is an example in the second article where a virtual gets inlined and can then be evaluated completely at compile time through constant propagation. In that case, the compiler/linker transformed the program to not use the class at all, and thus it should not contain any object or vtable.
Sub sb;
sb.bar(); //avoids vtable?
The above will never need to use a vtable for dispatch, as the runtime type is known (i.e. it's known to be the same as the compile-time/static type, namely Sub).
Super& sr = sb;
sr.bar(); //avoids vtable?
Super* srp = &sb;
srp->bar(); //avoids vtable?
In these cases, if the pointer/reference and usage appear in the same function, the optimiser may well be smart enough to avoid dispatch via a vtable. If the pointer or reference is passed to some other out-of-line function that migth be called with other types of pointers, then vtable-based dispatch will normally be needed.
More generally, the C++ Standard doesn't make any stipulations about how runtime polymorphism is implemented, so there is no guaranteed, portable way to eliminate "vtables".
That said, your best bets to minimise use of the vtable for dispatch are:
to mark overrides final when the freedom to override further is not actually required, and
to keep the implementation inline (even if implicitly - by having the function implementation in the class definition)
To see if either/both help, you'll have to experiment with or read the docs for your own compiler / tool-chain, optimisation flags etc..
An unused vtable may or may not be removed by the linker: you may want to experiment with cross-object linker optimisation flags if you have multiple translation units.

No RTTI but still virtual methods

C++ code can be compiled with run-time type information disabled, which disables dynamic_cast. But, virtual (polymorphic) methods still need to be dispatched based on the run-time type of the target. Doesn't that imply the type information is present anyway, and dynamic_cast should be able to always work?
Disabling RTTI kills dynamic_cast and typeid but has no impact on virtual functions. Virtual functions are dispatched via the "vtable" of classes which have any virtual functions; if you want to avoid having a vtable you can simply not have virtual functions.
Lots of C++ code in the wild can work without dynamic_cast and almost all of it can work without typeid, but relatively few C++ applications would survive without any virtual functions (or more to the point, functions they expected to be virtual becoming non-virtual).
A virtual table (vtable) is just a per-instance pointer to a per-type lookup table for all virtual functions. You only pay for what you use (Bjarne loves this philosophy, and initially resisted RTTI). With full RTTI on the other hand, you end up with your libraries and executables having quite a lot of elaborate strings and other information baked in to describe the name of each type and perhaps other things like the hierarchical relations between types.
I have seen production systems where disabling RTTI shrunk the size of executables by 50%. Most of this was due to the massive string names that end up in some C++ programs which use templates heavily.

Does 'final' specifier add any overhead?

Does using specifier final on a class or on a function add any memory or cpu overhead, or is it used at compile time only?
And how does std::is_final recognise what is final?
It actually can reduce overhead. And in rare cases, increase it.
If you have a pointer to a final class A, any virtual method calls can be de-virtualized and called directly. Similarly, a call to a virtual final method can be de-virtualized. In addition, the inheritance tree of a final class is fixed, even if it contains virtual parent classes, so you can de-virtualize some parent access.
Each of these de-virtualizations reduce or eliminate the requirement that a run-time structure (the vtable) be queried.
There can be a slight downside. Some coding techniques rely on vtable access to avoid direct access to a symbol, and then do not export the symbol. Accessing a vtable can be done via convention (without symbols from a library, just the header file for the classes in question), while accessing a method directly involves linking against that symbol.
This breaks one form of dynamic C++ library linking (where you avoid linking more than a dll loading symbol and/or C linkage functions that return pointers, and classes are exported via their vtables).
It is also possible that if you link against a symbol in a dynamic library, the dynamic library symbol load could be more expensive than the vtable lookup. I have not experienced or profiled this, but I have seen it claimed. The benefits should, in general, outweigh such costs. Any such cost is a quality of implementation issue, as the cost is not mandated to occur because the method is final.
Finally, final inhibits the empty base optimization trick on classes, where someone knows your class has no state, and inherits from it to reduce the overhead of "storing" an instance of your class from 1 byte to 0 bytes. If your class is empty and contains no virtual methods/inheritance, don't use final to avoid this being blocked. There is no equivalent for final functions.
Other than the EBO optimization issue (which only occurs with empty types), any overhead from final comes from how other code interacts with it, and will be rare. Far more often it will make other code faster, as directly interacting with a method enables both a more direct call of the method, and can lead to knock-on optimizations (because the call can be more fully understood by the compiler).
Marking anything except an empty type as final when it is final is almost certainly harmless at run time. Doing so on classes with virtual functions and inheritance is likely to be beneficial at run time.
std::is_final and similar traits are almost all implemented via compiler built-in magic. A good number of the traits in std require such magic. See How to detect if a class is final in C++11? (thanks to #Csq for finding that)
No, it's only used at compile-time
Magic (see here for further info - thanks Csq for link)

Why is the virtual keyword needed?

In other words, why doesn't the compiler just "know" that if the definition of a function is changed in a derived class, and a pointer to dynamically allocated memory of that derived class calls the changed function, then that function in particular should be called and not the base class's?
In what instances would not having the virtual keyword work to a programmer's benefit?
virtual keyword tells the compiler to implement dynamic dispatch.That is how the language was designed.
Without such an keyword the compiler would not know whether or not to implement dynamic dispatch.
The downside of virtual or dynamic dispatch in general is that,
It has slight performance penalty. Most compilers would implement dynamic dispatch using vtable and vptr mechanism, where the appropriate function to call is decided through vtable and hence an additional indirection is needed in case of dynamic dispatch.
It makes your class Non-POD.
One reason:
Consider base classes located in separate module, like library.
And derived classes in your application.
How would compiler knows during compiling the library that the given function is/must be virtual.
One of the main designing principles of C++ is that C++ does not incur overhead for features that are not used (the "zero-overhead principle"). This is because of a focus on high performance
This is why you need to opt in to features like virtual functions while in languages like Java, functions are virtual by default.
The compiler doesn't know, because it can't. It might be your intention, to not use virtual functions, because there's always a cost associated with every feature.

Access v-table at run-time

Is it possible to access a function's v-table at runtime? Can meta-information such as the number of different function versions be determined? This might be more of a theoretical question, but could a developer put a cap on the number of classes that can extend a given base class by making sure the v-table never exceeds a certain number of rows?
Is it possible to access a function's v-table at runtime? Can meta-information such as the number of different function versions be determined?
Not in a portable way. The standard does not even have the concept of virtual table, it is more of an implementation detail than a requirement, even if all implementations I know use vtables. In the general case there will not even be enough information available at runtime (i.e. the compiler does not need to store the number of entries in the vtable, as it sees the type and can count)
Could a developer put a cap on the number of classes that can extend a given base class by making sure the v-table never exceeds a certain number of rows?
Again no, but since this shows a misconception, it might be worth treating it apart. When a base class has any virtual functions the compiler (in all implementations that use vtables) will create the vtable and that table will have exactly 1 entry per virtual function in the base class (plus some additional data --typeinfo or pointer to it, offset to the beginning of the object or other implementation details). When a class extends that base class, it will not add new elements to that vtable, but rather create a separate vtable (or more, depending on the type hierarchy). If the derived function does not add any new virtual function, the vtable for the derived object will contain the exact number of elements that the original vtable had. That is, you can have a huge hierarchy of inheritances without that affecting the vtable layout at all. What will change are the typeinfo data stored and the pointers to each virtual function, that will refer to the final overrider
an meta-information such as the number of different function versions be determined?
No C++ doesn't support reflection. What you are trying to achieve is not possible in C++ AFAIK
Theoretically, yes, because it's stored in memory and you have access to it. In practice, there is no sane, portable way to do it, because the compiler is free to implement virtual functions in any way it wants, so you would have to dig through your compiler's source code to find out how/where to access the desired information and how to interpret it.
The only glimmer of hope I could imagine for your effort, is the handling of dynamic_cast. Each compiler, with corresponding library support, has some concept of traversing a hierarchy to achieve a dynamic cast. If you could hook into that traversal, you might then know something about how many levels of inheritance you are dealing with. That said, even if you made this work, it would be compiler-specific (as others have said) since such implementation is proprietary.
You can use the Debug Interface Access SDK or other debug support interfaces (gdb) for this sort of thing.
RTT data is more portable but may not have sufficient details for your project.
For your specific question on limiting the v-table and preventing it from being extended too far, you can try this method;
IDiaSymbol::get_classParente
Retrieves a reference to the class parent of the symbol.
HRESULT get_classParent (IDiaSymbol** pRetVal);
You can investigate all of the class related symbol types here, what you might want to do is enumerate all class types loaded, get_classParent recursively and keep a tally of all of the classes which extend your base.
Your class could also require symbols to be available on startup to help with enforcement.