Pointers to Members

Member Function Pointer Performance

How do member function pointers impact performance compared to virtual functions or std::function? Are there memory overhead considerations?

Abstract art representing computer programming

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.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved