Member Function Pointer Performance
How do member function pointers impact performance compared to virtual functions or std::function
? Are there memory overhead considerations?
Let's examine the performance characteristics of member function pointers compared to alternatives:
Memory Overhead
Here's a comparison of memory sizes:
#include <functional>
#include <iostream>
class Character {
public:
virtual void Attack() {}
void RegularAttack() {}
};
int main() {
// Size comparisons
std::cout << "Regular function ptr: " <<
sizeof(&Character::RegularAttack)
<< " bytes\n";
std::cout << "Virtual class size: " << sizeof(
Character) << " bytes\n";
std::cout << "std::function size: " << sizeof(
std::function<void()>)
<< " bytes\n";
}
Regular function ptr: 8 bytes
Virtual class size: 8 bytes
std::function size: 32 bytes
Performance Comparison
Here's a benchmark comparing different calling mechanisms:
#include <chrono>
#include <functional>
#include <iostream>
class Character {
public:
virtual void VirtualAttack() { count++; }
void DirectAttack() { count++; }
int count{0};
};
void BenchmarkCalls(const char* Name, auto Func,
int Iterations) {
auto start =
std::chrono::high_resolution_clock::now();
for (int i = 0; i < Iterations; i++) {
Func();
}
auto end =
std::chrono::high_resolution_clock::now();
auto duration =
std::chrono::duration_cast<
std::chrono::microseconds>(end - start);
std::cout << Name << ": " << duration.count()
<< "us\n";
}
int main() {
Character c;
void (Character::*memPtr)() = &
Character::DirectAttack;
std::function<void()> func = [&](){
c.DirectAttack();
};
const int iterations = 1000000;
// Direct call
BenchmarkCalls(
"Direct", [&](){ c.DirectAttack(); },
iterations);
// Member function pointer
BenchmarkCalls(
"Member Ptr", [&](){ (c.*memPtr)(); },
iterations);
// Virtual function
BenchmarkCalls(
"Virtual", [&](){ c.VirtualAttack(); },
iterations);
// std::function
BenchmarkCalls(
"std::function", [&](){ func(); },
iterations);
}
Direct: 3298us
Member Ptr: 3605us
Virtual: 3808us
std::function: 11404us
Key performance considerations:
- Direct function calls are fastest but least flexible
- Member function pointers have minimal overhead
- Virtual functions have vtable lookup overhead
std::function
has the most overhead but maximum flexibility
Memory considerations:
- Regular member function pointers: typically 8-16 bytes
- Virtual functions: add vtable pointer (usually 8 bytes) per object
std::function
: larger size for type erasure (typically 32+ bytes)
When to use each:
- Use direct calls when flexibility isn't needed
- Use member function pointers for runtime flexibility with good performance
- Use virtual functions for type-based polymorphism
- Use
std::function
when maximum flexibility is needed
The performance impact is usually negligible for most applications, but can matter in performance-critical code paths or when dealing with millions of calls per frame.
Pointers to Members
Learn how to create pointers to class functions and data members, and how to use them