Let's examine the performance characteristics of member function pointers compared to alternatives:
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
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:
std::function
has the most overhead but maximum flexibilityMemory considerations:
std::function
: larger size for type erasure (typically 32+ bytes)When to use each:
std::function
when maximum flexibility is neededThe 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.
Answers to questions are automatically generated and may not have been reviewed.
Learn how to create pointers to class functions and data members, and how to use them