Delegates and the Observer Pattern

std::function vs Function Pointer Performance

What's the overhead of using std::function compared to raw function pointers?

Abstract art representing programming

std::function provides more flexibility than raw function pointers but comes with some overhead. Let's examine the differences and when each might be appropriate.

Raw Function Pointers

Function pointers are simple and lightweight:

  • Fixed size (typically 8 bytes on 64-bit systems)
  • No heap allocation
  • Very fast to call (similar to regular function calls)
class Player {
public:
  using FnPtr = void(*)(int NewHealth);

  void SetDelegate(FnPtr Fn) {
    OnDamage = Fn;
  }

  void TakeDamage(int Damage) {
    Health -= Damage;
    if (OnDamage) OnDamage(Health);
  }

private:
  FnPtr OnDamage{nullptr};
  int Health{100};
};

void LogHealth(int NewHealth) {
  std::cout << "Health: " << NewHealth << '\n';
}

int main() {
  Player P;
  P.SetDelegate(LogHealth);
  P.TakeDamage(30);
}

std::function

std::function is more flexible but has overhead:

  • Variable size (typically 32 bytes for the object itself)
  • May require heap allocation for larger callables
  • Slightly slower call time due to type erasure
class Player {
 public:
  using Delegate = std::function<
    void(int NewHealth)>;

  void SetDelegate(Delegate D) {
    OnDamage = D;  
  }

  void TakeDamage(int Damage) {
    Health -= Damage;
    if (OnDamage) OnDamage(Health);
  }

 private:
  Delegate OnDamage;
  int Health{100};
};

int main() {
  Player P;

  // Can store free functions
  P.SetDelegate(LogHealth);

  // Can store lambdas with capture
  int LogCount{0};
  P.SetDelegate([&LogCount](int NewHealth) {  
    std::cout << "Health: " << NewHealth << '\n';
    LogCount++;
  });

  P.TakeDamage(30);
}

When to Use Each

Use raw function pointers when:

  • You only need to store simple function pointers
  • Performance is absolutely critical
  • Memory usage must be minimized

Use std::function when:

  • You need to store lambdas with captures
  • You need to store member functions
  • You want to store different types of callables
  • The flexibility is worth the small overhead

Remember that premature optimization is the root of all evil. Start with std::function for its flexibility, and only switch to raw function pointers if profiling shows it's necessary for your specific use case.

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

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 53 Lessons
  • 100+ Code Samples
  • 91% 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