> For the complete documentation index, see [llms.txt](https://nodejsdocs.gitbook.io/everthing-c++/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nodejsdocs.gitbook.io/everthing-c++/function-pointers-lambdas-and-call-mechanics.md).

# Function Pointers, Lambdas & Call Mechanics

This chapter explores how functions are treated as first-class citizens in C++. We'll look at different ways of invoking code: direct function calls, function pointers, functors, and lambdas — with an eye on performance implications like inline expansion, dispatch overhead, and instruction cache behavior.

***

### 1. Function Pointers

#### 1.1 Basics

```cpp
void greet() {
    std::cout << "Hello\n";
}

void (*fp)() = greet;
fp(); // prints Hello
```

* Function pointers hold addresses of functions.
* Used in callbacks, low-level event systems, and system programming.

#### 1.2 Function Pointer with Parameters

```cpp
int add(int a, int b) { return a + b; }
int (*operation)(int, int) = add;
std::cout << operation(5, 6); // 11
```

***

### 2. Lambdas

#### 2.1 Syntax

```cpp
auto add = [](int a, int b) { return a + b; };
std::cout << add(2, 3); // 5
```

* Anonymous function objects
* Captures external variables

#### 2.2 Capture Modes

```cpp
int x = 10;
auto lambda_by_val = [x]() { return x + 1; }; // capture by value
auto lambda_by_ref = [&x]() { x++; };          // capture by reference
```

#### 2.3 Lambdas and Performance

* Lambdas can be inlined by the compiler.
* With capture, lambdas become stateful functors (slightly heavier).
* Use `mutable` to allow modification of captured-by-value vars.

```cpp
auto f = [x]() mutable { x++; return x; };
```

***

### 3. Functors (Function Objects)

```cpp
struct Multiply {
    int operator()(int a, int b) const { return a * b; }
};

Multiply mult;
std::cout << mult(3, 4); // 12
```

* Can maintain state across invocations.
* Compiler aggressively inlines these.

#### Functor vs Lambda

| Feature             | Lambda             | Functor               |
| ------------------- | ------------------ | --------------------- |
| Syntax              | Short, clean       | Verbose               |
| Statefulness        | Yes (with capture) | Yes (member vars)     |
| Inlining            | Yes                | Yes                   |
| Reuse/Extensibility | No                 | Yes (can add methods) |

***

### 4. `std::function` — Type-Erased Callables

```cpp
#include <functional>

std::function<int(int, int)> func;
func = add;
func = [](int a, int b) { return a * b; };
```

* Holds any callable with matching signature.
* Uses type erasure (adds indirection & slight overhead).
* Avoid in high-frequency paths.

***

### 5. Advanced: Function Dispatch & Overheads

#### 5.1 Virtual Function Dispatch

```cpp
struct Base {
    virtual void foo() { std::cout << "Base"; }
};
struct Derived : Base {
    void foo() override { std::cout << "Derived"; }
};
```

* Virtual calls go through **vtable**.
* Adds indirection → **hurts branch prediction & inlining**.

#### 5.2 Inline vs Function Call

* Inlining removes call overhead.
* Compiler can inline lambdas and small functions.
* Too large = no inlining → use `__attribute__((always_inline))` or `inline` keyword.

***

### 6. Trick Questions & Quirks

#### Q1. Can a lambda return a function pointer?

```cpp
auto getFunc() -> int(*)(int, int) {
    return [](int a, int b) -> int { return a + b; };
}
```

✅ Yes — by explicitly stating return type.

***

#### Q2. Does this compile?

```cpp
std::function<void()> f = [] { std::cout << "Hello"; };
f();
```

✅ Yes — Lambdas can be assigned to `std::function`.

***

#### Q3. Which is faster: function pointer or lambda?

* If lambda is stateless → inlined → faster.
* Function pointer → cannot be inlined → slower due to indirect jump.

***

### 7. Pipeline Stalls, Branch Prediction & Dispatch Overhead

#### 7.1 Pipeline Stalls

* Function pointer calls introduce **indirect branches**, hard to predict.
* High stall rate in CPUs if many indirect jumps occur in inner loops.

#### 7.2 Branch Misprediction

* Virtual functions or indirect calls hurt **branch predictor**.
* Favor compile-time dispatch (e.g., templates, CRTP) in hot paths.

***

### 8. Summary

| Concept           | Tip / Insight                                       |
| ----------------- | --------------------------------------------------- |
| Function Pointers | Great for callbacks, not for perf-critical code     |
| Lambdas           | Preferred when small & stateless                    |
| Functors          | Best blend of performance + extensibility           |
| `std::function`   | Powerful but avoid in tight loops                   |
| Dispatch Cost     | Avoid indirect jumps in performance-sensitive paths |
| Inlining          | Inlining improves I-cache locality, branch predict  |

***

Next: Chapter 8 — Templates, CRTP, and Compile-Time Polymorphism
