Modern C++ Reference

C++ Programming Cheat Sheet

From "what does std::cout mean" to "I write lock-free telemetry engines for spacecraft." Modern C++ explained like you're human.

Baby Basics Getting Somewhere Actually Cooking Deep Shit Black Magic NASA Rules
Found 0 matching cards
1
Modern C++ Basics
iostream, auto, references, and ranges. Forget malloc and printf for a minute.
Hello Modern C++ — Streams & Namespaces
//  gives you streams for input and output
#include <iostream>
#include <string>

int main() {
    // std::cout is console out. << is the stream insertion operator.
    // Prefer '\n' over std::endl because endl forces a flush every time (slow!)
    std::cout << "Hello, Modern C++!\n";

    std::string name;
    std::cout << "Enter your callsign: ";
    std::cin >> name; // reads single word

    std::cout << "Welcome aboard, " << name << "!\n";
    return 0;
}
Compile with modern standard: g++ -std=c++20 main.cpp -o main. Always compile with at least C++17 or C++20 enabled!
auto Keyword — Let the Compiler Figure It Out
// auto deduces the exact type at COMPILE TIME (zero runtime cost)
auto speed = 299792458;          // deduced as int
auto pi = 3.1415926535;          // deduced as double
auto flag = true;                // deduced as bool
auto msg = "Don't Panic";        // deduced as const char*

// auto drops references & const by default! Use auto& or const auto& if you want them
int val = 100;
auto& ref = val;                 // ref is int& (modifying ref modifies val)
const auto& cref = val;          // cref is const int& (read-only reference)

// decltype(expr) inspects the declared type of an expression
decltype(val) anotherVal = 50;   // anotherVal is int
auto makes complex iterator types readable. Instead of writing std::vector<std::pair<std::string, int>>::const_iterator, just write auto it.
References (&) vs Pointers (*) — Safe Aliases
int x = 42;

// 1. A Reference is an alias (another name for the same variable).
// MUST be initialized, CANNOT be null, CANNOT be reseated to another var.
int& ref = x;
ref = 99; // x is now 99!

// 2. Pass-by-Reference in functions prevents slow deep copies
void boostEnergy(int& n) {
    n += 50; // modifies caller's variable directly
}

// 3. Const Reference: Fast (no copy) AND safe (cannot mutate)
void printBigData(const std::string& text) {
    std::cout << text << "\n";
    // text += "!"; // ERROR: cannot modify const reference
}
Default rule of thumb: Pass primitives (int, float, bool) by value. Pass objects/strings/structs by const T&.
std::string — Real Strings That Don't Suck
#include <string>
#include <iostream>

std::string s1 = "Apollo";
std::string s2 = "11";

// Concatenation with + just works!
std::string mission = s1 + " " + s2; // "Apollo 11"

// Useful methods
auto len = mission.length();           // or .size() -> 9
bool empty = mission.empty();          // false
std::string sub = mission.substr(0, 6);// "Apollo" (start, length)
mission.append(" - Moon Landing");

// Need C-style char* for an old C library? Use .c_str()
const char* cStr = mission.c_str();
In C++, std::string manages its own heap memory automatically and grows dynamically. No manual malloc or strcpy bugs.
Range-Based For Loops — Clean Iteration
#include <vector>
#include <iostream>

std::vector<int> coords = {10, 20, 30, 40, 50};

// Read-only (no copy, high performance)
for (const auto& c : coords) {
    std::cout << c << " ";
}

// Mutate in place (by non-const reference)
for (auto& c : coords) {
    c *= 2; // doubles each element in vector
}

// C++20 Structured Binding in range loop!
struct Point { int x, y; };
std::vector<Point> pts = {{1,2}, {3,4}};
for (const auto& [px, py] : pts) {
    std::cout << "X:" << px << " Y:" << py << "\n";
}
constexpr & Type Aliasing — Compile-Time Power
// 1. constexpr evaluated entirely at COMPILE TIME! Zero CPU work at runtime.
constexpr int square(int n) {
    return n * n;
}
constexpr int TABLE_SIZE = square(16); // computed by compiler as 256!

// 2. consteval (C++20) FORCES compile-time evaluation (errors if called at runtime)
consteval int mustBeConst(int v) { return v * 10; }

// 3. 'using' is modern C++ typedef (cleaner, works with templates)
using TelemetryID = uint64_t;
using StringList = std::vector<std::string>;
Prefer constexpr over preprocessor macros like #define TABLE_SIZE 256. constexpr is type-safe and scoped!
2
OOP & Core Abstractions
Classes, constructors, inheritance, and virtual dispatch done right.
Classes vs Structs — The Only Difference
// In C++, class and struct are identical EXCEPT FOR DEFAULT VISIBILITY:
// - 'struct' members default to PUBLIC
// - 'class' members default to PRIVATE

struct Vector2D {
    float x{0.0f}; // public by default! (in-class initializer)
    float y{0.0f};
};

class BankAccount {
private:
    double balance{0.0}; // hidden from outside

public:
    void deposit(double amount) {
        if (amount > 0) balance += amount;
    }
    double getBalance() const { return balance; }
};
C++ idiom: Use struct for plain passive data bags (POD). Use class when enforcing invariants and encapsulation.
Constructors & Member Initializer Lists
class Spaceship {
private:
    std::string callsign;
    int crewCount;
    const int launchYear; // const members MUST use initializer lists!

public:
    // 1. Parameterized Constructor with Initializer List (ALWAYS prefer this)
    Spaceship(std::string name, int crew, int year)
        : callsign(std::move(name)), crewCount(crew), launchYear(year) {
        // Body runs AFTER members are already constructed!
    }

    // 2. Default Constructor explicitly defaulted
    Spaceship() = default;

    // 3. Prevent implicit unwanted conversions using explicit
    explicit Spaceship(int crew) : callsign("Drone"), crewCount(crew), launchYear(2026) {}
};
Always mark single-argument constructors as explicit so the compiler doesn't accidentally cast an integer into your entire class!
const Methods & The 'this' Pointer
class TelemetrySensor {
private:
    double reading{0.0};
    mutable int accessCount{0}; // mutable CAN be modified in const methods

public:
    // Method marked const PROMISES not to mutate member variables
    double getReading() const {
        accessCount++; // legal because accessCount is mutable
        return reading;
    }

    // Method chaining using *this
    TelemetrySensor& setReading(double r) {
        this->reading = r;
        return *this; // return reference to current instance
    }
};

// Usage: sensor.setReading(98.6).setReading(101.2);
Inheritance & Access Specifiers
class Vehicle {
protected:
    float speed{0.0f}; // derived classes can access this, public cannot

public:
    void accelerate(float amount) { speed += amount; }
};

// 'public Vehicle' means Vehicle's public members stay public in Rocket
class Rocket : public Vehicle {
private:
    float fuelLevel{100.0f};

public:
    void igniteStage1() {
        speed += 1500.0f; // access protected base member
        fuelLevel -= 40.0f;
    }
};
Almost always use public inheritance. private or protected inheritance is rare and changes all base methods to hidden.
Virtual Functions & Dynamic Polymorphism
class Astronaut {
public:
    // ALWAYS make base class destructors virtual! (prevents memory leaks)
    virtual ~Astronaut() = default;

    // virtual enables runtime dynamic dispatch (vtables)
    virtual void performDuty() {
        std::cout << "Monitoring life support systems.\n";
    }
};

class Commander : public Astronaut {
public:
    // 'override' makes the compiler verify this matches a base virtual function!
    void performDuty() override {
        std::cout << "Authorizing orbital insertion burn.\n";
    }
};

// Calling through base pointer invokes Commander::performDuty at runtime!
Astronaut* astro = new Commander();
astro->performDuty(); // outputs Commander message!
delete astro;
Abstract Classes & Pure Virtual (= 0)
// Pure virtual method '= 0' makes class Abstract (cannot be instantiated)
class ILogger {
public:
    virtual ~ILogger() = default;
    virtual void log(const std::string& msg) = 0; // pure virtual
};

class ConsoleLogger : public ILogger {
public:
    void log(const std::string& msg) override {
        std::cout << "[LOG] " << msg << "\n";
    }
};

// 'final' on class prevents further inheritance
class LockedLogger final : public ConsoleLogger {};
C++ doesn't have an interface keyword like Java/C#. An abstract class with only pure virtual functions and a virtual destructor IS an interface.
3
Resource Management & RAII
Smart pointers, move semantics, and Rule of 0/3/5. Never leak memory again.
RAII — Resource Acquisition Is Initialization
// RAII Rule: Bind the lifetime of a resource (heap memory, file, socket, mutex)
// to the lifetime of a stack object! Destructor frees it AUTOMATICALLY when it leaves scope.

class FileHandler {
private:
    FILE* file;
public:
    FileHandler(const char* filename, const char* mode) {
        file = fopen(filename, mode);
    }
    ~FileHandler() {
        if (file) fclose(file); // guaranteed to run even on exceptions!
    }
};

void work() {
    FileHandler fh("telemetry.log", "w");
    // Do stuff... if error or return happens, fclose is still called!
}
std::unique_ptr — Exclusive Ownership Smart Pointer
#include <memory>

struct SensorData { int pressure; };

void processData() {
    // 1. Always create with std::make_unique (exception-safe & fast)
    auto sensor = std::make_unique<SensorData>();
    sensor->pressure = 1013;

    // 2. unique_ptr CANNOT BE COPIED! (exclusive single owner)
    // auto copy = sensor; // COMPILER ERROR!

    // 3. Ownership CAN be transferred with std::move
    std::unique_ptr<SensorData> newOwner = std::move(sensor);
    // sensor is now nullptr; newOwner owns the memory
} // memory is automatically deleted here. Zero runtime overhead vs raw pointer!
Rule: std::unique_ptr should be your default choice 95% of the time for dynamically allocated heap objects.
std::shared_ptr & std::weak_ptr — Shared Ownership
#include <memory>

struct Node {
    int value;
    std::shared_ptr<Node> next;
    // weak_ptr does NOT increment ref count (breaks circular leak cycles!)
    std::weak_ptr<Node> prev;
};

void example() {
    // std::make_shared allocates object + control block in 1 single memory chunk
    auto p1 = std::make_shared<Node>(); // use_count = 1
    {
        auto p2 = p1; // copy increases use_count to 2
        std::cout << p1.use_count(); // 2
    } // p2 goes out of scope -> use_count drops to 1

    // To use weak_ptr, must lock() it to get a temporary shared_ptr
    std::weak_ptr<Node> w = p1;
    if (auto locked = w.lock()) {
        locked->value = 42;
    }
} // p1 leaves scope -> count hits 0 -> memory safely freed
Move Semantics & Rvalues (std::move, T&&)
#include <vector>
#include <string>

// Lvalue: Has a name/address (e.g. variable x).
// Rvalue: Temporary value with no persistent name (e.g. "hi" + " world", 42).
// T&& is an Rvalue Reference: binds to temporary objects ready to be stolen!

class Buffer {
    int* data;
    size_t size;
public:
    // Move Constructor: Steals pointer instead of copying huge array!
    Buffer(Buffer&& other) noexcept
        : data(other.data), size(other.size) {
        other.data = nullptr; // zero out other so its destructor won't free it
        other.size = 0;
    }
};

std::vector<std::string> v;
std::string huge = "Gigabytes of telemetry data...";
v.push_back(std::move(huge)); // std::move casts huge to rvalue -> fast move!
The Rule of 0, 3, and 5
/*
 RULE OF ZERO: If your class uses standard types (string, vector, unique_ptr),
 write ZERO special member functions. Compiler generates safe defaults!

 RULE OF THREE (C++98): If you write any of:
 1. Destructor
 2. Copy Constructor
 3. Copy Assignment Operator
 ...you almost certainly must write all 3.

 RULE OF FIVE (Modern C++11+): When managing raw resources, write all 5:
*/
class ResourceHolder {
public:
    ~ResourceHolder();                                  // 1. Destructor
    ResourceHolder(const ResourceHolder&);              // 2. Copy Ctor
    ResourceHolder& operator=(const ResourceHolder&);  // 3. Copy Assign
    ResourceHolder(ResourceHolder&&) noexcept;          // 4. Move Ctor
    ResourceHolder& operator=(ResourceHolder&&) noexcept; // 5. Move Assign
};
Aim for the Rule of Zero. Use smart pointers and standard containers so you don't have to manually write copy/move logic.
Operator Overloading & Spaceship (<=>)
struct Vec2 {
    float x, y;

    // Overload +
    Vec2 operator+(const Vec2& rhs) const {
        return {x + rhs.x, y + rhs.y};
    }

    // C++20 Three-way comparison operator (Spaceship operator <=>)
    // Generates <, <=, ==, !=, >=, > AUTOMATICALLY!
    auto operator<=>(const Vec2&) const = default;
};

// Stream output operator overload (std::cout << vec)
std::ostream& operator<<(std::ostream& os, const Vec2& v) {
    return os << "(" << v.x << ", " << v.y << ")";
}
4
Modern STL & Algorithms
Vectors, hash maps, modern lambdas, ranges, and std::optional.
std::vector — Dynamic Contiguous Array
#include <vector>
#include <iostream>

std::vector<int> nums = {1, 2, 3};

// reserve() pre-allocates memory capacity to avoid re-allocations
nums.reserve(1000);

nums.push_back(4);               // appends element
nums.emplace_back(5);            // constructs element in-place (faster for objects)

nums[0] = 10;                    // unchecked indexing (blazing fast)
nums.at(1);                      // bounds-checked indexing (throws std::out_of_range)

auto first = nums.front();       // 10
auto last  = nums.back();        // 5
nums.pop_back();                 // removes last element
nums.clear();                    // size becomes 0 (capacity preserved)
Always call .reserve(N) on vectors if you know roughly how many items you will add! It prevents repeated heap reallocations.
std::unordered_map & std::map
#include <unordered_map>
#include <map>
#include <string>

// 1. std::unordered_map = Hash Table (O(1) average lookup, unordered)
std::unordered_map<std::string, int> thrust;
thrust["Merlin"] = 845;
thrust["Raptor"] = 2200;

// Check if key exists (C++20 .contains())
if (thrust.contains("Raptor")) {
    std::cout << thrust["Raptor"] << " kN\n";
}

// 2. std::map = Red-Black Tree (O(log N) lookup, ALWAYS sorted by key)
std::map<int, std::string> countdown;
countdown[3] = "Ignition";
countdown[1] = "Liftoff";
Modern Lambdas — Anonymous In-Line Functions
// Syntax: [captures](parameters) -> return_type { body }

int threshold = 50;

// Capture by value [=] or [threshold]
auto isHigh = [threshold](int val) -> bool {
    return val > threshold;
};

// Capture by reference [&] (can modify outer variables)
int counter = 0;
auto tick = [&counter]() { counter++; };

// Generic Lambda with auto parameters (C++14+)
auto printPair = [](const auto& a, const auto& b) {
    std::cout << a << ": " << b << "\n";
};
Algorithms & C++20 Ranges
#include <algorithm>
#include <ranges>
#include <vector>

std::vector<int> v = {5, 2, 8, 1, 9, 4};

// Modern C++20 std::ranges::sort (no need for v.begin(), v.end()!)
std::ranges::sort(v);

// Binary search / finding
bool found = std::ranges::binary_search(v, 8);

// Range Views pipeline (lazy evaluation! Zero allocations!)
auto evenSquares = v
    | std::views::filter([](int n) { return n % 2 == 0; })
    | std::views::transform([](int n) { return n * n; });

for (int n : evenSquares) {
    std::cout << n << " "; // 4 16 64
}
std::optional & std::variant (Type-Safe Unions)
#include <optional>
#include <variant>
#include <string>

// 1. std::optional: Replaces nullable pointers and magic error numbers (-1)
std::optional<int> findSensor(int id) {
    if (id == 42) return 100;
    return std::nullopt; // empty result
}
auto res = findSensor(42);
int val = res.value_or(0); // 100 if present, else fallback to 0

// 2. std::variant: Type-safe, memory-efficient tagged union
std::variant<int, double, std::string> packet;
packet = "Telemetry OK";
if (std::holds_alternative<std::string>(packet)) {
    std::cout << std::get<std::string>(packet) << "\n";
}
std::string_view & std::span — Zero-Copy Views
#include <string_view>
#include <span>
#include <iostream>

// string_view is just a pointer + length. ZERO memory allocation!
void parseHeader(std::string_view sv) {
    if (sv.starts_with("NASA")) { // C++20
        std::cout << "Valid NASA packet: " << sv.substr(5) << "\n";
    }
}

// std::span (C++20) represents any contiguous array view without copying
void printBytes(std::span<const uint8_t> buffer) {
    for (auto b : buffer) std::cout << static_cast<int>(b) << " ";
}
Use std::string_view for read-only function arguments instead of const std::string& whenever you might pass string literals or sub-slices!
5
Templates & Metaprogramming
Templates, fold expressions, C++20 concepts, and compile-time evaluation.
Templates — Generic Types and Functions
// 1. Function Template: Compiler generates concrete functions for each type used!
template <typename T>
T clampVal(T val, T minVal, T maxVal) {
    if (val < minVal) return minVal;
    if (val > maxVal) return maxVal;
    return val;
}

// 2. Class Template with Non-Type Template Parameter (e.g. fixed buffer size N)
template <typename T, size_t N>
class RingBuffer {
private:
    T buffer[N];
    size_t head{0};
public:
    void push(const T& item) { buffer[head++ % N] = item; }
};

RingBuffer<float, 128> gyroBuffer;
Variadic Templates & C++17 Fold Expressions
#include <iostream>

// 'Args... args' is a parameter pack containing ANY number of arguments
template <typename... Args>
void printAll(const Args&... args) {
    // C++17 Fold Expression: expands ((std::cout << arg1), (std::cout << arg2)...)
    ((std::cout << args << " "), ...);
    std::cout << "\n";
}

// Summing multiple arguments at compile-time
template <typename... Numbers>
auto sumAll(Numbers... nums) {
    return (... + nums); // fold over binary operator +
}

printAll("Orbit", 42, 3.14, 'A'); // Orbit 42 3.14 A
auto total = sumAll(10, 20, 30, 40);    // 100
C++20 Concepts & Constraints
#include <concepts>
#include <iostream>

// Define custom concept: must support + and be copyable
template <typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;

// Use concept directly in template parameter
template <Numeric T>
T calcAcceleration(T force, T mass) {
    return force / mass;
}

// Or with the ultra-concise 'auto' concept syntax
void printNumber(Numeric auto n) {
    std::cout << "Value: " << n << "\n";
}

// Passing std::string will trigger a clear, readable compiler error!
Concepts turn 500-line template error vomits into a clean single line error: "candidate template ignored: constraints not satisfied".
if constexpr — Compile-Time Branching
#include <type_traits>
#include <iostream>

template <typename T>
void serialize(const T& value) {
    // Discarded branch is NOT compiled for types that don't match!
    if constexpr (std::is_pointer_v<T>) {
        if (value) std::cout << *value << "\n";
    } else if constexpr (std::is_integral_v<T>) {
        std::cout << "Int: " << value << "\n";
    } else {
        std::cout << "Generic: " << value << "\n";
    }
}
6
NASA Rules & Game-Engine Grade C++
Lock-free atomics, jthreads, cache-line alignment, and JPL safety standards.
NASA JPL & MISRA Safety-Critical C++ Rules
RuleRationale
No Dynamic Memory after InitAllocate all heap during boot. Zero malloc/new during mission execution to prevent heap fragmentation crash.
Fixed Upper Loop BoundsEvery while/for loop MUST have a statically provable upper trip limit to guarantee termination.
No Unchecked ExceptionsExceptions introduce unpredictable control flow and non-deterministic latency. Use std::expected or return codes.
Zero Undefined BehaviorCompile with -Wall -Wextra -Wpedantic -Wconversion -Werror and sanitize with UBSan / ASan.
No Multiple Inheritance with StateAvoid diamond inheritance complexity. Prefer composition or interfaces with pure virtual methods only.
Spacecraft software runs millions of miles away without a restart button. Determinism & safety always beat convenience.
std::jthread, std::mutex & std::scoped_lock
#include <thread>
#include <mutex>
#include <iostream>

std::mutex telemetryMutex;
int globalPacketCount = 0;

void worker(std::stop_token st) {
    while (!st.stop_requested()) {
        {
            // RAII lock: locks on construction, unlocks automatically on exit!
            std::scoped_lock lock(telemetryMutex);
            globalPacketCount++;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

// C++20 std::jthread automatically requests stop and joins on destruction!
void launch() {
    std::jthread t1(worker);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
} // t1 automatically stops & joins cleanly right here!
std::atomic — Lock-Free High-Performance Concurrency
#include <atomic>

// std::atomic executes hardware-level atomic CPU instructions (LOCK XADD etc.)
// Zero OS kernel context-switches, zero mutex overhead!
std::atomic<uint64_t> txPackets{0};

void onPacketReceived() {
    // Atomic fetch-and-add
    txPackets.fetch_add(1, std::memory_order_relaxed);
}

// Compare-And-Swap (CAS) loop: backbone of lock-free data structures
std::atomic<int> head{0};
void updateMax(int newVal) {
    int curr = head.load();
    while (newVal > curr && !head.compare_exchange_weak(curr, newVal)) {
        // loops until successfully swapped without data race
    }
}
Cache Alignment & Hardware Cache Lines (alignas)
#include <new>

// Modern CPUs load memory in 64-byte Cache Lines.
// False Sharing: Two threads updating different variables on the SAME cache line
// will destroy multi-core performance!

struct alignas(64) ThreadCounter {
    std::atomic<uint64_t> counter{0};
    uint8_t pad[56]; // pad out the remaining 64 bytes
};

// Guaranteed each counter lives on its own dedicated cache line!
ThreadCounter coreCounters[16];
Preventing false sharing with alignas(64) in high-frequency trading or game engines can yield a 10x throughput boost.
+
C++ Standards Quick Reference & Headers
Key language evolution timeline & essential headers
C++ Standard Evolution Timeline
StandardGame-Changing Features
C++11auto, smart pointers, lambdas, move semantics (rvalues), range-for, nullptr, constexpr, threads.
C++14Generic lambdas, std::make_unique, relaxed constexpr, binary literals.
C++17std::string_view, std::optional, std::variant, structured bindings, if constexpr, fold expressions.
C++20Concepts, Ranges, std::jthread, Coroutines, Modules, consteval, std::format, Spaceship <=>.
C++23std::print / std::println, std::expected, deducing this, multidimensional subscript [x, y].
Essential Modern C++ Standard Headers
HeaderWhat it gives you
<iostream>std::cout, std::cin, std::cerr
<vector>std::vector dynamic array
<memory>std::unique_ptr, std::shared_ptr, std::make_unique
<algorithm>std::sort, std::find, std::ranges
<string_view>std::string_view zero-copy strings
<optional>std::optional nullable value container
<thread>std::jthread, std::this_thread
<mutex>std::mutex, std::scoped_lock
<atomic>std::atomic lock-free primitives
<concepts>std::integral, std::floating_point (C++20)