Hands-On High Performance Programming with Qt 5
上QQ阅读APP看书,第一时间看更新

Virtual functions

The first and foremost accusation raised against C++ in the early days was the allegedly high cost of virtual functions. Nowadays, this criticism seems to have come back in vogue in some programming communities, for example, among games developers. So, what about its performance costs?

As we know, virtual functions are implemented by means of vtables, that is, tables containing function pointers for all the virtual functions of a class. An instance of a class will contain a pointer to the global instance of this class's vtable. Hence, a call of virtual functions goes through two indirections; first, it follows the pointer to the vtable and then the pointer to the function. This cannot be good for performance, right? It's a classic example of pointer chasing, isn't it?

The direct cost of a virtual function call is taking the pointer to the vtable and following it. This could cause a cache miss but probably won't, if the vtable is accessed anywhere close to often. Then the pointed-to method will be called, which may again cause an instruction cache miss, but in tight loops, it probably won't.

The other cost of virtual function calls is indirect, as they could refuse to be inlined (but bear in mind that that's not always the case), disabling further compiler optimizations, as we will discuss in one of the following sections. 

An even more indirect cost of virtual function calls is the manner in which polymorphism is traditionally used, that is, by creating polymorphic objects dynamically using new. Dynamic memory allocations incur high costs regarding CPU time data locality, as we will see in one of following subsections, so overusing them would have a negative impact on performance. So, watch your program design!

So we can see, there is a cost to virtual functions but it's not so big that it would justify always avoiding them. Here, as always, the measure-first strategy is to be applied.