A language tour

The Power of C++

Zero-cost abstractions. The belief that you should pay only for what you use — in performance and in complexity.

scroll

01 — Zero-Cost Abstractions

Pay only for what you use

Bjarne Stroustrup's guiding principle: abstractions should cost nothing if you don't use them, and no more than hand-written code if you do. C++ proves this is achievable — high-level code that compiles to tight machine instructions.

"C++ is designed to allow you to express ideas, and if you don't know the ideas you want to express, C++ isn't going to help you much."

— Bjarne Stroustrup
zero_cost.cpp
#include <algorithm>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> v = { 3, 1, 4, 1, 5, 9, 2, 6 };

    // This range-based for loop compiles identically to a raw index loop
    int total = 0;
    for (const auto& x : v) total += x;

    // Lambda + algorithm — no virtual dispatch, inlined at compile time
    std::sort(v.begin(), v.end(),
        [](int a, int b) { return a > b; });

    // Same performance as hand-written quicksort on ints
    return 0;
}

The lambda passed to std::sort is not a pointer — it's an inlined callable. The compiler erases the abstraction entirely, generating the same code as if you wrote the comparison inline.


02 — Templates

Generic code with no runtime cost

C++ templates generate specialised code for each type at compile time. No boxing, no virtual dispatch, no type erasure overhead — the abstraction dissolves into optimised machine code before it ever runs.

templates.cpp
template <typename T>
T clamp(T val, T lo, T hi) {
    return val < lo ? lo : (val > hi ? hi : val);
}

// Concept constraint (C++20) — only accept arithmetic types
template <typename T>
requires std::is_arithmetic_v<T>
T lerp(T a, T b, float t) {
    return a + (b - a) * t;
}

int main() {
    auto fi = clamp(15,  0,  10);   // int version
    auto fd = clamp(0.7, 0.0, 1.0); // double version
    auto mid = lerp(0.0f, 100.0f, 0.5f);  // → 50.0
    return 0;
}

The compiler instantiates a separate clamp<int> and clamp<double> — two specialised functions, each as fast as hand-written code for that type.


03 — RAII

Resources tied to lifetime

Resource Acquisition Is Initialization is C++'s answer to manual memory management. Constructors acquire resources; destructors release them. When an object goes out of scope, cleanup happens automatically — no garbage collector required.

raii.cpp
#include <fstream>
#include <memory>
#include <string>

struct DatabaseConnection {
    DatabaseConnection(const std::string& url) { /* connect */ }
    ~DatabaseConnection() { /* disconnect automatically */ }
};

void process_data() {
    // File closes automatically at end of scope
    std::ifstream file("data.txt");

    // Memory freed automatically — no delete needed
    auto conn = std::make_unique<DatabaseConnection>("postgres://localhost");

    // Even if an exception is thrown here, both are cleaned up
    throw std::runtime_error("something went wrong");

    // conn.~unique_ptr() and file.~ifstream() run here — guaranteed
}

RAII makes exception safety tractable. Resources clean themselves up when their owner's lifetime ends — no finally blocks, no leak paths, no manual bookkeeping.


04 — Move Semantics

Transfer, don't copy

Modern C++ distinguishes between copying data and moving ownership. Move semantics let you transfer the guts of an object — its heap allocation, its file handle — without the cost of duplication. It changed how idiomatic C++ is written.

move_semantics.cpp
#include <string>
#include <vector>
#include <utility>

int main() {
    std::string a = "Hello, long string that lives on the heap";

    // Copy: allocates new memory, duplicates contents
    std::string b = a;         // a still valid, b is a full copy

    // Move: steals the heap buffer — O(1) regardless of string length
    std::string c = std::move(a); // a is now empty, c owns the buffer

    // Returning a local: automatically moved, not copied
    auto make_big_vector = []() -> std::vector<int> {
        std::vector<int> v(1'000'000);
        return v;  // RVO or move — no million-element copy
    };
    return 0;
}

The apostrophe in 1'000'000 is a C++14 digit separator — a small readability feature that lets you write large literals the way humans write them.


05 — Lambdas & Ranges

Expressive algorithms, no overhead

C++20's ranges library brings pipeline-style composition to C++ without virtual dispatch or heap allocation. Combined with lambdas, it lets you express complex transformations with the clarity of a functional language and the performance of C.

ranges.cpp
#include <ranges>
#include <vector>
#include <print>

int main() {
    std::vector<int> nums = { 1,2,3,4,5,6,7,8,9,10 };

    // Lazy pipeline — nothing computed until iteration
    auto result = nums
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * n; })
        | std::views::take(3);

    for (auto x : result)
        std::print("{} ", x);  // 4 16 36

    return 0;
}

The range pipeline is lazy — filter and transform produce no output until the for loop pulls values through. No intermediate vectors, no allocations.


06 — The Whole Picture

Why C++ still dominates

🎮

Games & Graphics

Unreal Engine, game engines, real-time renderers — the performance ceiling of C++ powers interactive media.

📊

High-Frequency Trading

Where microseconds matter, C++ is the only option. Latency is measured in cache misses, not abstraction layers.

🛡️

Backwards Compatibility

C++ code written in 1998 still compiles today. That longevity is a deliberate design value.

🧩

Multi-Paradigm

OOP, generic, functional, procedural — C++ supports them all and lets you pick the right tool for each problem.

🔬

Embedded Systems

RAII with no garbage collector, predictable destruction, and no runtime — ideal for real-time embedded code.

🌐

Infrastructure

Chromium, LLVM, most databases, video codecs — the software that runs the internet is written in C++.