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

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Member Function Pointers vs Virtual Functions
Why would we use member function pointers instead of virtual functions when we want to change behavior at runtime?
Member Function Pointers with Templates
Can we use member function pointers with templates to create generic callbacks that work with any class that has a specific method signature?
Async Member Function Pointers
How can we use member function pointers with asynchronous operations like std::async or thread pools?
Serializing Member Function Pointers
What's the best way to serialize/deserialize member function pointers for saving game state or network communication?
Lambda Member Function Pointers
Is it possible to create a member function pointer to a lambda that's stored as a class member?
Smart Pointers with Member Functions
How can we use member function pointers with smart pointers (shared_ptr, unique_ptr) effectively?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant