S7.0 What This Teaches
- Lambda syntax: parameters, return type, body
- Capture modes: by value, by reference, default captures
- Using lambdas with standard algorithms
std::functionfor storing callable objects- Returning lambdas from functions
mutablelambdas
S7.1 Lambda Syntax
// [capture](params) -> return_type { body }
// return type is usually inferred
auto add = [](int a, int b) { return a + b; };
auto greet = [](const std::string& name) -> std::string {
return "Hello, " + name + "!";
};
std::cout << add(3, 4) << "\n"; // 7
std::cout << greet("Alice") << "\n"; // Hello, Alice!
S7.2 Capture Modes
int x = 10, y = 20;
auto by_value = [x, y]() { return x + y; }; // copies of x and y
auto by_ref = [&x, &y]() { x++; return x + y; }; // references to x and y
auto all_val = [=]() { return x + y; }; // capture all by value
auto all_ref = [&]() { x++; y++; }; // capture all by reference
// mutable: modify the captured copy (not the original)
auto inc_copy = [x]() mutable { return ++x; }; // x in outer scope unchanged
[x, &y]) over default captures
([=], [&]). Explicit captures make it clear
what the lambda depends on.
S7.3 Lambdas with Algorithms
std::vector<int> v = {3, 1, 4, 1, 5, 9};
// sort descending
std::sort(v.begin(), v.end(), [](int a, int b){ return a > b; });
// find first even
auto it = std::find_if(v.begin(), v.end(), [](int x){ return x % 2 == 0; });
// filter to new vector
std::vector<int> big;
std::copy_if(v.begin(), v.end(), std::back_inserter(big),
[](int x){ return x > 3; });
S7.4 std::function
#include <functional>
std::function<int(int, int)> op;
op = [](int a, int b) { return a + b; };
std::cout << op(3, 4) << "\n"; // 7
op = [](int a, int b) { return a * b; };
std::cout << op(3, 4) << "\n"; // 12
std::function can store any callable with a matching signature.
It has overhead from type erasure - use auto for local lambdas
and std::function only when you need to store or pass callables
polymorphically.
S7.5 Returning Lambdas
auto make_adder(int n) {
return [n](int x) { return x + n; };
}
auto add5 = make_adder(5);
auto add10 = make_adder(10);
std::cout << add5(3) << "\n"; // 8
std::cout << add10(3) << "\n"; // 13
n by value, so each call to
make_adder creates a closure with its own copy of n.
S7.6 Example - All Together
// Lambdas - syntax, capture modes, algorithms, std::function, returning lambdas.
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
auto add = [](int a, int b) { return a + b; };
std::cout << "add(3,4)=" << add(3, 4) << "\n";
int offset = 10;
auto add_offset = [offset](int x) { return x + offset; };
std::cout << "add_offset(5)=" << add_offset(5) << "\n";
int counter = 0;
auto inc = [&counter]() { ++counter; };
inc(); inc(); inc();
std::cout << "counter=" << counter << "\n";
std::vector<int> v = {5, 3, 8, 1, 9};
std::sort(v.begin(), v.end(), [](int a, int b){ return a > b; });
std::cout << "sorted desc: ";
for (int x : v) std::cout << x << " ";
std::cout << "\n";
auto make_multiplier = [](int f){ return [f](int x){ return x * f; }; };
auto triple = make_multiplier(3);
std::cout << "triple(7)=" << triple(7) << "\n";
return 0;
}
add(3,4)=7
add_offset(5)=15
counter=3
sorted desc: 9 8 5 3 1
triple(7)=21
S7.7 Exercise
Exercise
- Write a lambda
is_primeand use it withcopy_ifto extract all primes from avector<int>of 1 through 30. - Write a function
apply(std::function<int(int)> f, int x)and call it with three different lambdas (square, double, negate). - Write a factory function
make_between_checker(int lo, int hi)that returns a lambda capturingloandhiand returningtrueif its argument is in range.
S7.8 Common Mistakes
Dangling reference capture
std::function<int()> get_lambda() {
int local = 42;
return [&local]() { return local; }; // dangling: local is gone after return
}
Forgetting mutable
int n = 5;
auto f = [n]() { return ++n; }; // error: n captured by value is const by default
mutable to modify a value-captured variable inside
the lambda.std::function overhead in performance-critical code
std::function uses type erasure and may allocate. In tight
loops, prefer auto or template parameters for callables.
S7.9 Key Terms
| Term | Meaning |
|---|---|
| lambda | Inline anonymous function object; syntax [capture](params){ body } |
| capture clause | [] specifies which outer variables the lambda can access |
| capture by value [x] | Lambda gets its own copy of x at the time of creation |
| capture by reference [&x] | Lambda holds a reference to x; changes are visible outside |
| mutable | Allows a value-captured variable to be modified inside the lambda |
| closure | Lambda together with its captured environment |
| std::function<R(Args)> | Type-erased callable wrapper; stores any callable with matching signature |