A game engine has this class :
class MouseListener{
public :
MouseListener();
virtual void OnMouseDown(int mx,int my);
virtual void OnMouseUp(int mx,int my);
.
.
.
};
Each object that wants to listen to mouse input , have to inherent that class and override it's methods . To not have to declare a new type each time , the class is modified to :
class MouseListener{
public :
MouseListener();
std::function <void(MouseListener*,int,int)>OnMouseDown;
std::function <void(MouseListener*,int,int)>OnMouseUp;
.
.
.
};
now using the class can be done this way :
MouseListener * m = new MouseListener();
m->OnMouseDown = [](MouseListener * thiz,int x,int y){
//// do something
};
From the input system , only the functions of MouseListener that are not null ( assigned ) are called ( with thiz = the mouse listener ). knowing that the class is used from an external library ( static link ) , which is better in terms of performance ?
NOTE : None of those function will be called unless a mouse event is received , when that happens , the appropriate function is called for each object listening to mouse input ( not supposed to be lot , <50)
Virtual functions are by definition slower than their non-virtual counterparts; we wanted to measure the performance gains from inlining; using virtual functions would make the difference even more pronounced. In this particular example, CLANG 10 compiler inlined the functions and unrolled the test loop two times.
Code wrapped into std::function is always slower than inlining code directly into calling place. Especially if your code is very short, like 3-5 CPU instructions.
A virtual function allows derived classes to replace the implementation provided by the base class. The compiler makes sure the replacement is always called whenever the object in question is actually of the derived class, even if the object is accessed by a base pointer rather than a derived pointer.
Virtual functions ensure that the correct function is called for an object, regardless of the type of reference (or pointer) used for function call. Functions are declared with a virtual keyword in base class. The resolving of function call is done at runtime.
It really depends on the usage of the virtual function vs. the function object.
although std::function
may be slower than a virtual call*, std::function
has short buffer optimization , which may prevent dynamic memory allocation (which you would probably have in the virtual version).
this itself may outperform anything you might do with regular polymorphism.
Internally (but not guaranteed), the std::function
object anyway uses a virtual call for the type erasure, so I'd say the difference is negligible.
A tip - make sure to check if the std::function
is valid (by calling if(static_cast<bool>(myFunction))
). the compiler will insert a check to see if the function is empty. if not, the program will throw std::bad_function_call
. the developer check will make the compiler remove his check and the code related to std::bad_function_call
when optimizations are turned on, leaving much "smoother" assembly code.
when dealing with performance and C++ in my experience, it's much more important to optimize away memory allocations, inter-thread-contention and bad data structures which work bad with the cache. usually, it's much more worthy optimizations than optimizing CPU-stuff away (like virtual function vs. std::function
)
*A decent compiler can implement the type erasure as a virtual function + the given lambda as inlined function. theoretically, it should not be slower than a regular virtual function. on the other hand, if the function object gets a non-inlinable callable, like a function pointer, it may use two indirection in order to launch the function. this may be slower than a regular virtual call. it depends.
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