C++ Functions

Functions & Lambdas

Functions, overloading, and the crucial choice C++ forces on you that managed languages hide: pass by value or by reference.

C++20 3 Topics
01

Functions & Overloading

C++ functions declare a return type and typed parameters. Overloading allows many functions with one name but different parameter lists, and default arguments let callers omit trailing parameters.

C++ — Overloading & Defaults
// returnType name(params) { body }
int add(int a, int b) { return a + b; }

// Overloading — same name, different parameter types
double add(double a, double b) { return a + b; }

// Default arguments — greet() or greet("Hi")
void greet(std::string msg = "Hello") {
    std::cout << msg;
}
greet();            // "Hello"
greet("Hi there");  // "Hi there"

// Declare before use, or provide a forward declaration:
int square(int n);   // prototype — defined later
Default arguments go in the declaration, not the definition, and only trailing parameters may have them. Unlike Python, they're evaluated per call, so a default like vector<int>() is fresh each time.
02

Pass by Value vs Reference

This is the choice that defines C++ performance. By value copies the argument. By reference (&) passes an alias, so no copy is made and the function can modify the original.

C++ — The Three Passing Styles
// by value — copies, caller's variable unchanged
void byValue(int x) { x = 99; }

// by reference — no copy, MODIFIES the caller's variable
void byRef(int& x) { x = 99; }

// by const reference — no copy, cannot modify (the default for big objects)
void byConstRef(const std::vector<int>& v) {
    std::cout << v.size();   // reads, never copies
}

int n = 5;
byValue(n);   std::cout << n;   // 5 — unchanged
byRef(n);     std::cout << n;   // 99 — modified
✓Rule of thumb: pass small types (int, double) by value; pass big objects (vector, string, classes) by const T&; use non-const T& only when you deliberately want to mutate the caller's object.
03

Lambdas

A lambda (C++11) is an anonymous function you can define inline and pass to STL algorithms. The [] capture list controls which surrounding variables it can access.

C++ — Lambdas & Captures
#include <algorithm>

// [capture](params) { body }
auto square = [](int x) { return x * x; };
square(5);        // 25

// capture by value [=] or by reference [&]
int factor = 3;
auto scale = [factor](int x) { return x * factor; };   // copies factor
scale(10);       // 30

// pass a lambda to an STL algorithm
std::vector<int> nums = {1, 2, 3, 4, 5};
int evens = std::count_if(nums.begin(), nums.end(),
    [](int x) { return x % 2 == 0; });   // 2

// sort by a custom comparator
std::sort(nums.begin(), nums.end(),
    [](int a, int b) { return a > b; });   // descending
Capturing by reference [&] is a dangling-reference trap: if the lambda outlives the captured variable (stored and called later), it references freed memory. Capture by value [=] when the lambda may escape the current scope.
✓

Quick Quiz

1. Passing by value does what to the argument?
2. Big objects should typically be passed as…
3. Overloaded functions must differ in…
4. In a lambda, [&] captures surrounding variables…
5. Default arguments may be given to…