thecodex.expert · The Codex Family of Knowledge
Language Reference

C++

C with classes, templates, and RAII — zero-overhead abstractions for game engines, browsers, compilers, and every performance-critical system.

Language Reference C++23 · C++20 widely deployed Static typing Last verified:
New to C++? This is the reference encyclopedia — dip in anytime. To learn step by step, start the C++ Course →
Canonical Definition

C++ is a general-purpose, statically typed, compiled programming language that extends C with classes, templates, RAII-based resource management, and the Standard Template Library — providing zero-overhead abstractions for systems programming, game engines, and high-performance applications.

📑 C++ Reference — All Topics

Classes & RAII

Constructors, destructors, copy/move semantics, RAII.

Templates & STL

Function templates, class templates, vector, map, algorithm.

Modern C++

C++11/14/17/20/23: auto, lambdas, smart pointers, concepts.

What is C++

Nearly 50 years old — and C++26 just finished standardization in March 2026.

Setup and Compilers

GCC, Clang, or MSVC — a feature being in the standard doesn't mean your compiler has it yet.

Variables and Types

auto never makes C++ dynamically typed — the type is still fixed at compile time.

Control Flow

The range-based for loop eliminated most manual index bookkeeping, and its bugs too.

Functions

C has no overloading at all — C++ resolves it by parameter types, at compile time.

Inheritance and Polymorphism

Forget virtual, and an overridden method silently calls the BASE version instead.

Smart Pointers

unique_ptr can't be copied, only moved — which guarantees zero chance of a double-free.

Move Semantics

std::move() doesn't move anything itself — it's purely a cast, nothing more.

References

Not a pointer in disguise — a true alias that can never be reseated or null.

Operator Overloading

std::string's + isn't compiler magic — it's the same mechanism your own class can use.

STL Containers

vector should be your default — reach for list only with a specific reason.

STL Algorithms

A hand-written sort loop is more likely to have a bug than std::sort itself.

Lambda Expressions

[=] copies, [&] references — and getting it wrong dangles a real reference.

Exceptions

Stack unwinding calls every local destructor automatically — RAII makes exceptions safe.

Namespaces

Two libraries can each define a Vector class with zero conflict between them.

Concurrency

Forget join() on a std::thread, and the whole program calls std::terminate.

Concepts and Constraints

A bad template argument used to mean pages of unreadable error — not anymore.

Coroutines

C++20 shipped the keywords — almost no ready-to-use types to pair them with.

Memory Management

Mixing new with delete[] is undefined behavior — one more reason to avoid both.

Multiple Inheritance

Two shared ancestors, one diamond problem — virtual inheritance is the fix.

Preprocessor and Macros

A macro has zero type checking — constexpr and templates do the job better.

Standard Library

std::expected finally gives C++ a typed way to return a value or an error.

Build Systems

CMake never compiles anything itself — it generates the files that do.

Testing

No built-in test runner exists — Google Test and Catch2 fill that real gap.

Undefined Behaviour

push_back can silently invalidate every iterator into the vector.

C++ Standards History

C++11 was such an overhaul it's often called the language's second birth.

One sentence

C++ gives you everything C offers — raw performance, direct hardware access, manual memory management — and layers on top the most powerful abstraction mechanisms in any mainstream language: classes, templates, and RAII.

What C++ is

C++ is a general-purpose, statically typed, compiled programming language created by Bjarne Stroustrup at Bell Labs, evolving from "C with Classes" (1979) to C++ with its first standardisation in 1998 (C++98). C++ extends C with classes, inheritance, operator overloading, templates (generic programming), exceptions, namespaces, and the Standard Template Library (STL). C++ compiles to native machine code with zero runtime overhead — no VM, no garbage collector. Memory management is manual (like C) but disciplined through RAII: resources are acquired in constructors and released in destructors, making cleanup automatic and exception-safe.

C++ is used wherever maximum performance and control are required: game engines (Unreal Engine, Unity runtime), browsers (Chromium, Firefox), compilers (Clang, GCC), databases (MySQL, MongoDB), high-frequency trading systems, embedded firmware, and virtually every operating system component. It is one of the most complex mainstream languages — ISO C++23 spans over 2,000 pages.

C++hello.cpp
#include <iostream>
#include <string>
#include <vector>

int main() {
    // C++ streams replace printf
    std::cout << "Hello, World!" << std::endl;

    // std::string — not a char array
    std::string name = "Priya";
    std::cout << "Hello, " << name << "!" << std::endl;

    // std::vector — dynamic array (not a C array)
    std::vector<int> scores = {95, 88, 72, 91};
    scores.push_back(85);

    // Range-based for loop (C++11)
    for (int score : scores) {
        std::cout << score << " ";
    }
    std::cout << std::endl;

    // auto — type inference (C++11)
    auto pi = 3.14159;
    auto message = std::string("typed as string");

    return 0;
}

Classes and OOP

C++classes.cpp
#include <iostream>
#include <string>
#include <stdexcept>

class BankAccount {
private:
    std::string owner_;   // trailing _ convention for members
    double balance_;

public:
    // Constructor
    BankAccount(std::string owner, double balance)
        : owner_(std::move(owner)), balance_(balance) {}

    // Destructor — runs automatically when object goes out of scope
    ~BankAccount() {
        std::cout << owner_ << " account closed\n";
    }

    void deposit(double amount) {
        if (amount <= 0) throw std::invalid_argument("Amount must be positive");
        balance_ += amount;
    }

    double getBalance() const { return balance_; }  // const = does not modify

    // Operator overloading
    friend std::ostream& operator<<(std::ostream& os, const BankAccount& acc) {
        return os << "Account(" << acc.owner_ << ": " << acc.balance_ << ")";
    }
};

int main() {
    BankAccount acc("Priya", 1000.0);
    acc.deposit(500.0);
    std::cout << acc << std::endl;  // Account(Priya: 1500)
}   // acc.~BankAccount() called automatically here

RAII — Resource Acquisition Is Initialisation

RAII is C++'s most important idiom. It ties resource lifetimes (memory, file handles, network connections, mutexes) to object lifetimes. When an object is constructed, it acquires a resource. When the object is destroyed (goes out of scope), the destructor releases it — automatically and even during stack unwinding from exceptions. This makes C++ resource management safe without a garbage collector. Smart pointers are RAII wrappers around raw pointers.

C++raii.cpp
#include <memory>
#include <fstream>
#include <iostream>

void process_file(const std::string& path) {
    // RAII: file closed automatically when stream goes out of scope
    std::ifstream file(path);
    if (!file.is_open()) throw std::runtime_error("Cannot open: " + path);

    std::string line;
    while (std::getline(file, line)) {
        std::cout << line << "\n";
    }
}   // file.~ifstream() closes the file here — even if exception thrown

void smart_pointers() {
    // unique_ptr: single owner — freed when pointer goes out of scope
    auto p1 = std::make_unique<int>(42);
    std::cout << *p1 << "\n";   // 42
    // p1 freed automatically here

    // shared_ptr: reference-counted — freed when last owner gone
    auto p2 = std::make_shared<std::string>("hello");
    auto p3 = p2;   // both p2 and p3 own the string
    std::cout << p2.use_count() << "\n";  // 2
}   // string freed here when both p2 and p3 destroyed

Templates

C++ templates enable generic programming — writing code that works for any type, resolved at compile time. Unlike Java generics (erased at runtime) or Go generics, C++ templates are fully reified: the compiler generates a specialised version of the code for each type it is used with. This enables maximum performance (no boxing, no virtual dispatch overhead) but increases compile time and binary size.

C++templates.cpp
#include <iostream>
#include <vector>
#include <algorithm>

// Function template
template<typename T>
T max_val(T a, T b) { return a > b ? a : b; }

// Class template
template<typename T>
class Stack {
    std::vector<T> data_;
public:
    void push(T val) { data_.push_back(std::move(val)); }
    T pop() {
        if (data_.empty()) throw std::runtime_error("empty stack");
        T val = std::move(data_.back());
        data_.pop_back();
        return val;
    }
    bool empty() const { return data_.empty(); }
};

// Template with concept constraint (C++20)
template<typename T>
requires std::totally_ordered<T>
T clamp(T val, T lo, T hi) {
    return std::clamp(val, lo, hi);
}

int main() {
    std::cout << max_val(3, 7) << "\n";         // 7 (int)
    std::cout << max_val(3.14, 2.71) << "\n";  // 3.14 (double)

    Stack<std::string> s;
    s.push("hello");
    s.push("world");
    std::cout << s.pop() << "\n";  // world
}

Move semantics and the rule of five

C++11 introduced move semantics — transferring ownership of resources from one object to another without copying. A move constructor and move assignment operator "steal" the internal resources of a temporary or expiring object (an rvalue) rather than copying them. The rule of five: if you define any of (1) destructor, (2) copy constructor, (3) copy assignment, (4) move constructor, (5) move assignment, you should define all five — because a custom destructor implies resource management that the compiler's defaults won't handle correctly.

C++move_semantics.cpp
#include <iostream>
#include <string>

class Buffer {
    char* data_;
    size_t size_;
public:
    explicit Buffer(size_t size) : data_(new char[size]), size_(size) {
        std::cout << "Allocated " << size << " bytes\n";
    }
    ~Buffer() { delete[] data_; }  // destructor

    // Copy constructor — expensive: copies all data
    Buffer(const Buffer& other) : data_(new char[other.size_]), size_(other.size_) {
        std::copy(other.data_, other.data_ + size_, data_);
        std::cout << "Copied " << size_ << " bytes\n";
    }

    // Move constructor — cheap: steals the pointer
    Buffer(Buffer&& other) noexcept
        : data_(other.data_), size_(other.size_) {
        other.data_ = nullptr;  // leave source in valid empty state
        other.size_ = 0;
        std::cout << "Moved\n";
    }

    // Copy/move assignment omitted for brevity — should follow same pattern
};

Buffer makeBuffer() { return Buffer(1024); }  // NRVO or move

int main() {
    Buffer b1(512);                  // Allocated
    Buffer b2 = b1;                  // Copied (b2 is independent copy)
    Buffer b3 = std::move(b1);       // Moved (b1 now empty)
    Buffer b4 = makeBuffer();        // Moved or NRVO (no copy)
}

The Standard Template Library (STL)

The STL provides containers, algorithms, and iterators as orthogonal components. Containers: vector (dynamic array), map/unordered_map (sorted/hash map), set/unordered_set, list (doubly linked), deque, stack, queue, priority_queue. Algorithms: sort, find, transform, accumulate, count_if, copy. Any algorithm works with any container via iterators — the decoupling that makes the STL extensible.

C++stl.cpp
#include <vector>
#include <map>
#include <algorithm>
#include <numeric>
#include <iostream>

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

    // Algorithms work on any container via iterators
    std::sort(v.begin(), v.end());             // in-place sort
    auto it = std::find(v.begin(), v.end(), 8);  // O(n) find

    // transform: apply function to each element
    std::vector<int> squared(v.size());
    std::transform(v.begin(), v.end(), squared.begin(),
                   [](int x) { return x * x; });  // C++11 lambda

    // accumulate: fold
    int sum = std::accumulate(v.begin(), v.end(), 0);

    // Ordered map (red-black tree internally)
    std::map<std::string, int> word_count;
    word_count["hello"]++;
    word_count["world"]++;
    for (auto& [word, count] : word_count) {   // C++17 structured bindings
        std::cout << word << ": " << count << "\n";
    }
}

Modern C++ (C++11 through C++23)

StandardKey additions
C++11auto, range-for, lambdas, move semantics, smart pointers, constexpr, thread, nullptr, initialiser lists
C++14Generic lambdas, variable templates, [[deprecated]]
C++17Structured bindings, if constexpr, std::optional, std::variant, std::filesystem, fold expressions, parallel algorithms
C++20Concepts, ranges, coroutines (co_await), modules, std::format, span, three-way comparison (<=>)
C++23std::expected, std::print, std::stacktrace, std::generator, import std
Commonly confused
C and C++ are different languages. C++ is not a superset of C — there are valid C programs that are not valid C++ (e.g. VLAs, implicit int, K&R function definitions). "I know C" does not mean "I know C++." The object model, memory management idioms, and standard library are fundamentally different.
new/delete are not the right tools in modern C++. Raw new and delete are error-prone — they require matching every new with a delete and are not exception-safe. In modern C++ (C++11+), use std::make_unique and std::make_shared instead. Raw pointers should only appear at low-level API boundaries.
C++ exceptions have costs even when not thrown. C++ exception handling ("zero-overhead exceptions" in Clang/GCC with LLVM/libunwind) has essentially zero cost on the happy path but significant overhead when an exception is actually thrown. Some performance-critical codebases (Google, game engines) disable exceptions entirely (-fno-exceptions) and use error codes instead.
How this connects
Requires first
Enables

The C++ object model and vtables

C++ virtual dispatch uses a vtable (virtual function table). For each class with virtual functions, the compiler generates a vtable: an array of function pointers, one per virtual function. Each object of that class stores a hidden vptr (vtable pointer) as its first data member. Calling a virtual function: dereference vptr to get the vtable, then call the function at the correct index. Cost: two pointer dereferences + one indirect call — typically one cache miss on first call, then cached. final (C++11) allows the compiler to devirtualise calls when the dynamic type is known. Devirtualisation is a key optimisation — the compiler can often prove at compile time which function will be called and inline it, eliminating virtual dispatch entirely.

Template metaprogramming and constexpr

C++ templates were shown to be Turing-complete by Erwin Unruh in 1994 — the compiler emits prime numbers as warning messages at compile time. Template metaprogramming (TMP) is a technique where computation happens entirely at compile time in the type system. C++11 constexpr made compile-time computation more accessible: functions marked constexpr can execute at compile time when their inputs are compile-time constants. C++20 concepts constrain template parameters with readable error messages instead of the famously cryptic TMP error walls. C++20 consteval forces compile-time evaluation.

The C++ Core Guidelines and safe subsets

Bjarne Stroustrup and Herb Sutter maintain the C++ Core Guidelines (github.com/isocpp/CppCoreGuidelines) — a collaboratively developed set of rules for writing correct, efficient modern C++. Key rules: use smart pointers (never raw new/delete), avoid raw arrays (use std::array or std::vector), use std::span for non-owning views. The Guideline Support Library (GSL) provides gsl::span, gsl::not_null, and other helper types. The US NSA and CISA (2022–2024) have recommended that new systems software be written in memory-safe languages instead of C/C++, citing that 70% of Microsoft and Google CVEs are memory safety issues in C/C++ code.

Specification reference

ISO/IEC 14882:2020 — C++20 standard. iso.org/standard/79358.html. Stroustrup, B. (2013). The C++ Programming Language (4th ed.). Addison-Wesley. Meyers, S. (2014). Effective Modern C++. O'Reilly Media. C++ Core Guidelines: github.com/isocpp/CppCoreGuidelines.

Sources

1
ISO/IEC 14882:2020. C++20 Standard. iso.org/standard/79358.html.
2
Stroustrup, B. (2013). The C++ Programming Language (4th ed.). Addison-Wesley.
3
Meyers, S. (2014). Effective Modern C++. O'Reilly Media. — Best practices for C++11/14.
4
Stroustrup, B. & Sutter, H. C++ Core Guidelines. github.com/isocpp/CppCoreGuidelines.
5
cppreference.com. C++ reference. en.cppreference.com. — Comprehensive standard library reference.
Source confidence: High Last verified: Primary source: ISO/IEC 14882 · cppreference.com