C++ — Reference

Source: https://en.cppreference.com/w/cpp

C++

  • Created: 1979 (as “C with Classes”) by Bjarne Stroustrup at Bell Labs; renamed C++ in 1983
  • Latest stable: C++23 (ISO/IEC 14882:2024, published 2024); C++26 in progress
  • Paradigms: multi-paradigm — procedural, object-oriented, generic, functional, metaprogramming
  • Typing: static, nominal, with type inference (auto), concepts (C++20)
  • Memory: manual (RAII + smart pointers); no GC
  • Compilation: AOT compiled to native, separate compilation + link
  • Primary domains: systems, embedded, games (engines), HFT/trading, browsers, OS kernels, scientific computing, GPU/CUDA hosts
  • Official docs: https://en.cppreference.com/w/cpp ; https://isocpp.org/

1. At a glance

  • Standardized by ISO/IEC JTC1/SC22/WG21. Three-year cadence: C++17 (2017), C++20 (2020 — modules, concepts, ranges, coroutines), C++23 (2024 — import std, std::expected, std::print, mdspan), C++26 (publication 2026 — reflection, sender/receiver, contracts, profiles).
  • Major implementations: GCC (libstdc++ — Linux default, conservative), Clang/LLVM (libc++ — Apple default, Android, fast feature uptake), MSVC (Microsoft STL — open-source since 2019), Apple Clang (lags ~1yr behind upstream), Intel oneAPI DPC++ (SYCL + CUDA-like), NVIDIA HPC SDK (former PGI). Pre-historical: EDG (frontend for many embedded compilers).
  • Backwards-compatible with C at the source/ABI boundary (mostly — C++20 designated initializers narrowed the gap; some C constructs like flexible array members aren’t directly supported); routinely used to host other languages’ runtimes (V8, SpiderMonkey, JSC, CPython internals, JVM HotSpot, Lua C++ wrappers, ART/Dalvik).
  • Tooling rebooted around LSP via clangd (LLVM project, the universal C++ LSP — VS Code, Neovim, Emacs, JetBrains) and modules in C++20+. ccls historic alternative. Source-Based Code Coverage in Clang (-fprofile-instr-generate -fcoverage-mapping).
  • ABI stability is a perennial topic — neither GCC’s libstdc++ nor Clang’s libc++ guarantees ABI across major versions; cross-vendor STL mixing is unsupported. C++ Committee deliberately broke ABI in C++23 for std::regex (rejected at last minute); ABI conservatism is a major reason C++ evolves slower than peers.

2. Getting started

  • Install: Linux: apt install g++ or dnf install gcc-c++. macOS: xcode-select --install (Apple Clang). Windows: Visual Studio Build Tools or MSYS2/MinGW-w64. Cross-platform: download from https://gcc.gnu.org/ or https://releases.llvm.org/.

  • Version managers: none official. Use distro packages, Homebrew (brew install llvm), or Conan/vcpkg toolchain files. nix-shell / Docker for reproducibility. Compiler matrix as of 2026: GCC 15 (full C++23, partial C++26 reflection); Clang 19 (full C++23, partial C++26 + experimental reflection); MSVC 19.42 / VS 17.12 (full C++23 / /std:c++latest); Apple Clang lags ~1 year behind upstream Clang.

  • Hello, world (C++23):

    import std;            // C++23 standard-library module
    int main() { std::println("Hello, world!"); }

    Compile: g++ -std=c++23 hello.cpp -o hello or clang++ -std=c++23 -fmodules hello.cpp. Project file equivalent (CMake 3.30+):

    cmake_minimum_required(VERSION 3.30)
    project(hello CXX)
    set(CMAKE_CXX_STANDARD 23)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    add_executable(hello hello.cpp)
  • Project layout: no enforced layout. Common: src/, include/<project>/, tests/, CMakeLists.txt. CMake’s “modern target-based” style is dominant — declare add_library(foo ...) + target_include_directories(foo PUBLIC include), consumers target_link_libraries(bar PRIVATE foo) and propagation is automatic.

  • Build tools: CMake 3.30+ is de facto (target-based, presets, FetchContent, FILE_SET for modules); Meson (Python config, fast — used by GNOME, systemd, Mesa, GStreamer); Bazel (Google, hermetic, monorepo); xmake (Lua config, batteries-included); Make; Ninja (low-level, used as backend for CMake/Meson — produces optimal incremental builds). Package managers: vcpkg (Microsoft, 2400+ ports, manifest mode vcpkg.json) and Conan 2 (JFrog, Python config, binary cache via Artifactory/CCI), plus CPM.cmake (CMake-only wrapper around FetchContent), Hunter, build2.

  • REPL/playground: Cling / xeus-cling (Jupyter, LLVM-based interpreter); Compiler Explorer (godbolt.org — every compiler, every version, view asm output side-by-side); C++ Insights (cppinsights.io — shows AST and what the compiler “actually” sees, esp. useful for templates / coroutines / structured bindings).

3. Basics

  • Primitives: bool, char/wchar_t/char8_t/char16_t/char32_t, fixed-width int8_tint64_t (via <cstdint>), float/double/long double, C++23 extended floating-point std::float16_t/std::bfloat16_t/std::float32_t/std::float64_t/std::float128_t. Literals: 0x, 0b, 0 (octal), digit separators 1'000'000 (C++14), raw strings R"(...)", user-defined literals 42_km, type-deduced literal suffixes 42u, 3.14f, 42uz (C++23 size_t).
  • Variables: auto x = 1; (deduced), const (immutable), constexpr (compile-time const, also fns), consteval (immediate fn — must run at compile time, C++20), constinit (initialized at compile time, no static init order fiasco, C++20). Block scope; RAII destruction in reverse construction order. Class Template Argument Deduction (CTAD, C++17): std::pair p(1, 'a'); instead of std::pair<int, char>.
  • Control flow: if/else, if constexpr (compile-time conditional, branches not taken are not instantiated — replaces SFINAE for many cases), if consteval (C++23), switch (with [[fallthrough]] since C++17), for, range-for for (auto& x : v), init-statements in if/switch (C++17: if (auto it = map.find(k); it != map.end()) {...}), while, do-while, structured bindings auto [k, v] = pair; (C++17), auto [k, v] : map for map iteration.
  • Functions: default args, overloading, templates, auto return type (C++14), trailing return type auto f() -> int, deducing this (C++23 — auto& f(this auto& self) { ... } for CRTP without the boilerplate). Lambdas [capture](args) -> ret { ... }; generic lambdas [](auto x){...} (C++14); templated lambdas []<class T>(T x){...} (C++20); static lambdas (C++23 — no captures, no implicit this). First-class via std::function / function pointers. std::function_ref (C++26) for non-owning callable references.
  • Strings: std::string (owning, SBO 15-22 chars depending on STL), std::string_view (non-owning, C++17 — careful with lifetimes), std::format (C++20), std::print/println (C++23). No native interpolation; use std::format("{} {}", a, b) or std::print("{:>10.2f}\n", pi). C++26 is bringing more: std::format with runtime format strings (currently compile-time only without vformat), embedded escape handling.
  • Collections: std::array<T, N> (stack), std::vector (dynamic, contiguous), std::deque (double-ended, segmented), std::list / std::forward_list (rarely the right choice), std::map/std::unordered_map, std::set/std::unordered_set, std::tuple, std::pair, std::span (C++20 — non-owning contiguous view), std::mdspan (C++23 — multi-dim non-owning), std::flat_map/std::flat_set / std::flat_multimap/std::flat_multiset (C++23 — sorted-vector-based, far better cache behavior than tree-based for ≤~100 elements). External: absl::flat_hash_map (3x faster than std::unordered_map), folly::F14, boost::container::flat_map.

4. Intermediate

  • Generics: templates over types, non-type values, and template templates. C++20 concepts constrain templates: template<std::integral T>. CTAD (Class Template Argument Deduction). Variadic templates + parameter packs. Abbreviated function templates: void f(auto x) is shorthand for template<typename T> void f(T x).
  • Modules: C++20 export module foo; / import foo;. import std; (C++23) replaces <iostream> etc. Build-system support is still maturing — CMake 3.28+ (target_sources(foo PUBLIC FILE_SET CXX_MODULES FILES bar.cppm)) with Ninja 1.11+ for module-dependency scanning (P1689 protocol). Compiler support: Clang 16+, GCC 14+ (partial), MSVC 19.30+. Modules emit a BMI (binary module interface, .pcm for Clang, .ifc for MSVC) that’s reused across TUs.
  • Namespaces: namespace foo { ... }, nested namespace foo::bar, anonymous namespaces for TU-local symbols, using declarations and directives. inline namespace for ABI versioning (std::__1:: in libc++).
  • Error handling: exceptions (throw/try/catch); std::expected<T,E> (C++23) for value-or-error with monadic ops and_then/or_else/transform/transform_error; std::optional<T> with monadic ops too; assertions via <cassert> and the proposed contracts in C++26. noexcept participates in overload resolution and codegen — std::vector::push_back uses noexcept(is_nothrow_move_constructible_v<T>) to decide whether to move or copy on grow.
  • Concurrency: std::thread, std::jthread (C++20, joins on dtor + cancellation token via std::stop_token), std::mutex/std::shared_mutex, std::atomic<T>, std::atomic_ref<T> (C++20, atomic operations on non-atomic memory), std::condition_variable, std::future/std::async. Synchronization primitives (C++20): std::latch (one-shot countdown), std::barrier (reusable), std::counting_semaphore<N>. Coroutines (C++20): co_await/co_yield/co_return. std::generator (C++23). Parallel STL: std::execution::par/par_unseq/unseq — GCC/Clang use TBB; MSVC uses its own.
  • I/O & networking: <iostream>, <fstream>, std::filesystem (C++17), <print> (C++23 — std::print("hello {}\n", name) thread-safe). No standard networking yet (std::net deferred to C++26+); use Asio (standalone or Boost.Asio), liburing for Linux io_uring, libuv for cross-platform event loop.
  • Stdlib highlights: <ranges> (C++20) views & pipelines (v | views::filter(odd) | views::transform(sq) | ranges::to<vector>()), <chrono> (calendars, time zones, parsing in C++20 with std::chrono::parse), <format> (std::format("{:>10.2f}", 3.14)), <source_location> (line/file/function info without macros), <bit> (std::popcount, std::countl_zero, std::rotl), <numbers> (pi_v<T>, e_v<T>), <random>, <regex>, <stacktrace> (C++23 — std::stacktrace::current()), <mdspan> (C++23 — multi-dimensional non-owning view), <flat_map>/<flat_set> (C++23 — sorted-vector-based, better cache behavior than tree-based).

5. Advanced

  • Memory model: explicit. Use std::unique_ptr / std::shared_ptr / std::weak_ptr over new/delete. Custom allocators via Allocator concept; std::pmr::polymorphic_allocator for arena-style with runtime polymorphism (monotonic_buffer_resource, unsynchronized_pool_resource, synchronized_pool_resource). Alignment via alignas/alignof. Memory order (memory_order_*) on atomics; the C++ memory model (since C++11) defines happens-before with sequenced-before, synchronizes-with, modification order. Object lifetime rules around std::launder, placement new, implicit-lifetime types (C++20), std::start_lifetime_as (C++23).
  • Concurrency deep dive: atomics with explicit memory order, lock-free queues, std::stop_token cooperative cancellation, executors (TS/proposed), std::latch/std::barrier (C++20). C++26 adds std::execution (sender/receiver model, P2300 — async composition that subsumes futures, channels, and coroutines), std::hazard_pointer/std::rcu for lock-free deletion, parallel sort scheduling, std::async_scope. Lock-free libraries: folly::ProducerConsumerQueue, boost::lockfree, moodycamel::ConcurrentQueue (mpmc, fastest).
  • FFI: extern "C" for C linkage. Direct interop with C; complex with other languages via C wrappers, SWIG, pybind11 + nanobind (Python — nanobind is 4x smaller bindings + 6x faster JIT), cppyy (auto-bindings via Cling), CXX + autocxx (Rust — type-safe bidirectional, used at Mozilla, Google), JNI (Java) / Project Panama FFM (modern), N-API / node-addon-api (Node), WebAssembly via emscripten or Cheerp.
  • Reflection: none in C++23 beyond typeid / std::source_location / <type_traits>. Static reflection (^^, [: :], P2996) is targeted for C++26 — Clang has an experimental implementation as of 2024-25. The Reflection TS proposed for C++23 was rejected in favor of P2996’s cleaner design. Compile-time reflection will subsume most TMP / macro use cases (serialization, GUI binding, ORM mapping, ABI dump).
  • Performance tooling: perf (Linux, sampling profiler), Intel VTune (microarchitectural events, top-down analysis), AMD uProf, valgrind/cachegrind/callgrind (instrumented, slow but exact), heaptrack (allocation profiler), gperftools (Google), Tracy (frame profiler for games, sub-ns precision), Optick, Easy Profiler, Visual Studio Profiler (Windows), Xcode Instruments (macOS). Sanitizers (-fsanitize=address,undefined,thread,memory,leak,dataflow,hwaddress) — ASan + UBSan are mandatory in CI for any new C++ code in 2026. [[nodiscard]], [[likely]]/[[unlikely]] (C++20), __builtin_expect, [[assume]] (C++23). PGO (-fprofile-generate/-fprofile-use, typically 5-20% wins), LTO (-flto), ThinLTO (parallel, scales to large monorepos). Post-link optimization: BOLT (Meta — 5-15% wins on top of PGO+LTO), Propeller (Google), AutoFDO.
  • Build acceleration: ccache (cache by source hash), sccache (Mozilla, distributed, S3/Redis backend), distcc (distributed compilation), icecream (LLVM-aware distributed), FASTBuild, EngFlow / Goma / Bazel remote cache for monorepos. Typical 5-20x speedup on incremental builds.

6. God mode

  • Templates as a Turing-complete metalanguage: SFINAE → enable_if → C++20 concepts + requires clauses. CRTP (template<class D> struct Base { auto& self() { return static_cast<D&>(*this); } }). Deducing this (C++23) replaces most CRTP — auto& self(this auto& self). Compile-time TMP libraries: boost::mp11, boost::hana (Louis Dionne, value-based metaprogramming), brigand, metal, kvasir::mpl, frozen (compile-time std::unordered_map), ctre (compile-time regex, Hana Dusíková — single-header, faster than runtime regex).
  • constexpr / consteval / constinit: entire algorithms run at compile time; consteval requires immediate evaluation. C++20 allows std::vector and std::string in constexpr. C++23 added if consteval (cleaner alternative to std::is_constant_evaluated()). C++26 adds constexpr cast from void*, broader floating-point support, constexpr std::function.
  • Coroutines machinery: customize via promise_type (return type, initial_suspend/final_suspend, await_transform); awaitables implement await_ready/await_suspend/await_resume. Stackless, heap-allocated by default — HALO (Heap Allocation eLision Optimization) often elides it. Coroutine libraries: cppcoro (Lewis Baker), folly::coro (Meta), unifex (sender/receiver implementation), Asio C++20 awaitables, libunifex.
  • Modules + header units: import <vector>; produces a BMI (binary module interface). Build systems must scan for import/module declarations (P1689) — CMake/Ninja support is mandatory. GCC 14+, Clang 16+, MSVC 19.30+ all support C++20 modules; ecosystem (Boost, Qt, libfmt) shipping module interfaces through 2025-26. Header units (import <header>;) bridge legacy #include.
  • Reflection (C++26): ^^T produces a reflection value (a std::meta::info); [: e :] splices it back into source. P2996 is the merged proposal; Clang-experimental builds available. Will subsume most TMP, codegen macros, and tools like boost::pfr / magic_enum.
  • Placement new + EBO (Empty Base Optimization) + [[no_unique_address]] (C++20, [[msvc::no_unique_address]] for MSVC ABI compat) for zero-overhead composition. Pairs with stateless allocators / unit-struct policies to give zero-overhead generics.
  • std::launder: required to bless pointers after object lifetime tricks (e.g., reusing storage via placement new of a different type). Gets right answer where compilers would assume aliasing-free.
  • Custom allocators: Allocator concept, std::pmr for runtime polymorphism, NUMA-aware allocation, slab/arena allocators. Mimalloc (Microsoft), jemalloc (Meta/FreeBSD), tcmalloc (Google), rpmalloc, snmalloc (Microsoft) — typical 5-30% speedups over default glibc malloc on multi-threaded allocators.
  • Link-time tricks: --gc-sections (drop unused code), --icf=safe/--icf=all (identical-code-folding — Chromium saves 10-15 MB), section-based code layout (-ffunction-sections -fdata-sections), BOLT (Meta’s post-link binary optimizer, 5-15% on top of PGO), Propeller (Google), Embedded ELF.
  • UB catalog awareness: signed overflow, OOB access, use-after-free, strict aliasing violations, unsequenced modifications, data races, type-punning via pointer cast (use std::bit_cast C++20 instead), reading uninitialized memory, integer divide by zero, invalid nullptr dereference, exceeding vector::reserve, double delete, returning ref to local. Use UBSan/ASan/MSan/TSan religiously. CFI (Control Flow Integrity): -fsanitize=cfi + LTO catches indirect-call type confusion.
  • Embedding: C++ embeds well into anything that takes a C ABI; the runtime dependencies are minimal (libstdc++/libc++, libgcc/compiler-rt, libc). For tiny embedded: -fno-exceptions -fno-rtti -nostdlib++ and bring your own minimal std.

Standard library implementations

  • libstdc++ (GCC) — Linux default, conservative, mature. Pair with mature GCC for full C++23.
  • libc++ (LLVM) — Apple default, Android default, faster std::string SBO (22 chars vs libstdc++‘s 15), often first with new C++ features. Migrating to libc++ is common for compile-time and binary-size wins.
  • MS STL (Microsoft) — Open-source since 2019 (github.com/microsoft/STL), full C++23 in VS 17.10+, debug iterators by default in Debug builds.
  • NVIDIA libcudacxx — heterogeneous standard library; same code on CPU and GPU.
  • EASTL (EA), Folly (Meta), Abseil (Google) — production-tested replacements for std types where defaults are too slow or feature-thin. folly::F14FastMap is 1.5-2x faster than std::unordered_map.

7. Idioms & style

  • Naming: no single convention — Google uses snake_case for vars, CamelCase for types; LLVM uses CamelCase for types and camelBack for methods; std uses all snake_case. Pick one and clang-format it.
  • Formatter: clang-format (Google/LLVM/Microsoft/Mozilla/Chromium/WebKit styles built in; custom .clang-format for project). Linter: clang-tidy (modernize-, bugprone-, performance-, readability-, cert-, cppcoreguidelines-, hicpp-*). include-what-you-use for include hygiene.
  • Idiomatic patterns: RAII for everything (lock guards, file handles, allocations); rule of zero/three/five; pass by value-and-move; const-correctness; prefer enum class; prefer std::array / std::span over C arrays; std::unique_ptr over new; auto for verbose type names; AAA (Almost Always Auto, Herb Sutter); CRTP / type erasure / std::variant over void*; value semantics over reference semantics where possible; small-buffer optimization (small_vector, inline_vector) for hot paths.
  • Reviewers look for: ownership semantics (raw pointers in API surface are smell), lifetime issues (dangling refs, iterators invalidated mid-loop), noexcept correctness (esp. for move ctors), value-category mistakes (move from const, dangling rvalue refs), thread-safety annotations (Clang’s [[clang::guarded_by]]), allocator awareness in hot paths, missing [[nodiscard]], exception safety levels (basic / strong / nothrow).
  • Modern guideline references: C++ Core Guidelines (Stroustrup + Sutter, isocpp.github.io), Google C++ Style Guide, LLVM Coding Standards, Mozilla C++ Portability Guide, Microsoft C++ Coding Standards. GSL (Guidelines Support Library) provides gsl::span, gsl::not_null, gsl::Expects/Ensures.

8. Ecosystem

  • Build systems: CMake 3.30+ (target-based modern style, presets, FetchContent, FILE_SET CXX_MODULES), Meson (Python-config, fast, Mesa+systemd use it), Bazel (Google, hermetic, monorepo-scale), xmake (Lua-config, batteries-included), premake (Lua → other generators), Ninja as the canonical low-level build runner.
  • Package managers: Conan 2.x (JFrog, Python-config, supports binary cache via Artifactory/CCI), vcpkg (Microsoft, manifest mode + classic mode, 2400+ ports), CPM.cmake (CMake-only, FetchContent wrapper), Hunter (legacy), build2 (full system: build + dep manager).
  • GUI: Qt 6.x (LGPL/commercial, dominant cross-platform), wxWidgets, Dear ImGui (immediate-mode, ubiquitous in tools/games), JUCE (audio + plugins), GTKmm, Slint (Rust-backed, embedded-friendly), FLTK (tiny), Sciter (HTML/CSS UI in native).
  • Game engines: Unreal Engine 5 (Epic), CRYENGINE, Godot (core in C++; scripting in GDScript/C#), O3DE (Linux Foundation, ex-Lumberyard), Bevy (Rust, not C++ but adjacent).
  • HPC/scientific: Eigen (linear algebra header-only), Armadillo, Boost, Kokkos (Sandia, performance-portable parallelism), RAJA (LLNL), OpenMP 5.x, MPI (OpenMPI, MPICH, Intel MPI), CUDA, HIP (AMD), SYCL (Khronos, Intel oneAPI, AdaptiveCpp/hipSYCL), TBB, HPX (asynchronous parallel runtime).
  • ML/inference: PyTorch C++ frontend (LibTorch), TensorFlow C++ API, ONNX Runtime, TensorRT, llama.cpp (Georgi Gerganov — runs LLMs on CPU/GPU/Metal with GGUF quantization, huge influence), whisper.cpp, MLX (Apple, Metal/M-series).
  • Web/network: Drogon (async, fast), Crow (Flask-like), cpp-httplib (single-header), Boost.Beast (Asio-based HTTP/WebSocket), Boost.Asio + standalone Asio, gRPC, uWebSockets (very fast), userver (Yandex async framework), restinio.
  • Serialization: Protocol Buffers, Cap’n Proto, FlatBuffers (Google), MessagePack, nlohmann/json (header-only), simdjson (Daniel Lemire, multi-GB/s parser), glaze (compile-time JSON), boost::serialization.
  • Testing: GoogleTest (most common), Catch2 v3 (header + cpp now), doctest (single-header, fast compile), Boost.Test, ut (boost::ut, single-header C++20), snitch (no-exception, embedded-friendly), Lest. Property-based: rapidcheck. Mocking: GMock, trompeloeil.
  • Doc tools: Doxygen, Sphinx + Breathe + Exhale, Standardese, mkdocs + Doxygen, hdoc.
  • Logging: spdlog (header/static, ubiquitous, sub-μs format), Boost.Log, glog (Google), quill (low-latency, async).
  • Where it’s used: browsers (Chromium, Firefox, WebKit), databases (PostgreSQL extensions, MongoDB, MySQL, ClickHouse, DuckDB, RocksDB, Cassandra C++ driver), Adobe/Autodesk creative apps (Photoshop, AutoCAD, Maya), financial trading systems (Jane Street has OCaml, but most HFT is C++), embedded firmware (cars, planes, medical), Microsoft Office, all major game engines, LLVM itself, V8 / SpiderMonkey / JSC, Unreal/Unity native code, parts of Windows / macOS / iOS / Android frameworks, Linux kernel adjacent code (kernel proper is C95, but userspace tools and kernel modules use C++).

9. Gotchas

  • Undefined behavior is everywhere: signed-integer overflow, OOB array access, dereferencing null/invalid pointers, use-after-free, uninitialized reads, strict-aliasing violations, double-frees, unsynchronized data races. UBSan + ASan + TSan are not optional in serious code.
  • Most vexing parse: Widget w(); declares a function, not a default-constructed Widget. Use Widget w{}; or auto w = Widget{};.
  • Initializer-list constructor preference: std::vector<int> v{3, 0}; is {3, 0} (size 2), not “3 zeros.” Use std::vector<int> v(3, 0).
  • Object slicing: copying a derived into a base by value drops the derived parts. Pass polymorphic types by reference / smart pointer.
  • Returning references to locals / dangling iterators after container reallocation. auto& back = v.back(); v.push_back(x); use(back); is UB if push_back reallocated.
  • std::vector<bool> is not a container of bool (proxy refs). Use std::vector<char> or boost::dynamic_bitset if you need real bools.
  • Implicit narrowing conversions in non-brace-init contexts. int x = 1.5; silently truncates; int x{1.5}; errors.
  • ABI fragility: std::string SBO sizes differ across libstdc++ vs libc++; mixing across libraries causes corruption. Standard libraries are not ABI-compatible across major versions either.
  • Headers vs modules ordering: macros leak in headers; module imports do not. Mixing requires explicit #include before any import.
  • Move-from objects are still destructible but in unspecified state; don’t reuse without reassigning.
  • Template error messages without concepts can be 200 lines; use concepts and static_assert.
  • std::shared_ptr cycles leak. Break with std::weak_ptr.
  • auto&& is universal reference, not rvalue reference. In for (auto&& x : range) it preserves value category — usually what you want.
  • Implicit bool conversions from int/void* can lead to surprising overload resolution.
  • Captures in lambdas: [=] captures by value (incl. *this as pointer copy in pre-C++17; [=, *this] for value copy in C++17+), [&] by reference (dangling risk). Be explicit.
  • std::optional<T&> is not in the standard (rejected). Use T* or std::reference_wrapper<T>.
  • NRVO vs copy elision rules changed in C++17 (guaranteed copy elision for prvalues) — pre-C++17 code may have surprises.
  • C++20 modules + inline functions — visibility rules differ subtly from headers; some libraries shipping with both header and module interfaces have ABI gotchas.
  • std::regex is slow — 5-100x slower than RE2, ctre, Hyperscan. Prefer alternatives for hot paths.
  • #include <iostream> is fat — pulls thousands of LOC. Use <print> (C++23) or forward declares.

Compile-time landscape (2026)

C++ compilation is famously slow. Modern strategies:

  • Precompiled headers (PCH) — 2-5x speedups on header-heavy code.
  • Modules — eliminate redundant parsing across TUs. CMake 3.28+ + Ninja 1.11+ scanning is mandatory.
  • Unity / jumbo builds — concatenate .cpp files; reduces re-parsing but breaks anonymous namespaces. Common in Chromium, UE.
  • include-what-you-use (IWYU) — minimize transitive includes.
  • #pragma once — universally supported now, faster than include guards on some compilers.
  • Forward declarations + pimpl idiom — break compile-time deps.
  • ccache / sccache — content-addressed compile cache; remote backend lets a team share a build cache.
  • distcc / icecream / Goma / Bazel remote — distributed compilation farms.

Interop with other languages

C++ is the universal lingua franca of native FFI. Common bidirectional paths:

OtherToolDirectionNotes
Cextern "C"bothDirect; mangle/unmangle aware
Rustcxx (David Tolnay)both, safeUsed by Mozilla (Servo), Google (Chromium), Linux kernel R4L
Rustautocxx (Google)C++ → RustGenerates Rust bindings from C++ headers
RustbindgenC/C++ → RustLower-level, less safety
RustcbindgenRust → C/C++Header generation
Pythonpybind11bothHeader-only, mature, standard for C++ Python ext
Pythonnanobind (Wenzel Jakob)both4x smaller bindings, 6x faster compiles
PythoncppyyC++ → PythonJIT bindings via Cling
Java/JVMJNI + Project Panama FFMbothFFM (JDK 22+) replaces JNI
JavaScript/Nodenode-addon-apibothN-API stable ABI
GocgobothCostly border crossing
SwiftC++ interop (Xcode 15+)bothFirst-class as of 2023
WASMemscripten, CheerpC++ → WASMProduction-grade
.NET / C#C++/CLI, P/Invoke, CppSharpbothC++/CLI Windows-only

Carbon

Carbon (Google, public 2022) is positioned as a “successor language” with bidirectional C++ interop, modern syntax (no preprocessor, generics with constraints, explicit pointers, no UB by default in safe mode). Still pre-1.0 in 2026 — not production-ready, but worth tracking as the heir-apparent if it ships. Compare with Herb Sutter’s cppfront / cpp2 (also experimental “10x simpler C++”) and Sean Baxter’s Circle (C++ extension with reflection + safety).

CMake modern target-based style

Modern CMake (post-3.15) is target-centric: each library declares its own usage requirements, consumers pick them up automatically via target_link_libraries.

cmake_minimum_required(VERSION 3.30)
project(myproj CXX)
 
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)   # for clangd
 
add_library(core)
target_sources(core
    PRIVATE src/core/foo.cpp src/core/bar.cpp
    PUBLIC FILE_SET HEADERS BASE_DIRS include FILES include/core/foo.hpp include/core/bar.hpp
    PUBLIC FILE_SET CXX_MODULES FILES src/core/utils.cppm   # C++20 module
)
target_include_directories(core PUBLIC include)
target_compile_features(core PUBLIC cxx_std_23)
target_compile_options(core PRIVATE
    $<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -Wpedantic>
    $<$<CXX_COMPILER_ID:MSVC>:/W4>
)
 
# Find third-party with vcpkg or Conan
find_package(fmt CONFIG REQUIRED)
target_link_libraries(core PUBLIC fmt::fmt)
 
add_executable(app src/main.cpp)
target_link_libraries(app PRIVATE core)
 
# Testing
enable_testing()
add_subdirectory(tests)

CMakePresets.json (3.19+) shares dev configurations across IDEs/CI:

{
  "version": 6,
  "configurePresets": [
    {
      "name": "default",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" }
    }
  ]
}

Modern best practices (Core Guidelines distilled)

The C++ Core Guidelines (Stroustrup + Sutter) and the C++ Core Guidelines Support Library (GSL) condense decades of experience. Highlights every modern C++ codebase should follow:

  • R.20 — Use unique_ptr or shared_ptr to represent ownership. Raw pointers are non-owning observers.
  • F.16 — Take rvalue references where you’ll sink. void push(T&& x) { storage_.push_back(std::move(x)); }.
  • C.21 — Rule of Zero. Don’t write copy/move/destroy unless you must. Let the compiler generate them.
  • CP.51 — Use std::jthread over std::thread. Automatic join + stop_token.
  • ES.20 — Always initialize. Default-initialized primitives are UB on read.
  • SL.con.1 — Prefer std::vector over arrays. Use std::array for fixed-size stack storage.
  • Per.4 — Don’t optimize prematurely. Measure. PGO usually beats hand-tuning.
  • Per.11 — Move computation from runtime to compile time. constexpr everything that doesn’t depend on input.
  • NL.16 — Use a conventional class member declaration order. public → protected → private; types → constructors → destructor → methods → data.

Real-world allocator + container performance (2024 microbenchmarks)

On a typical x86_64 modern CPU (Zen 4 / Sapphire Rapids):

  • std::unordered_map (libstdc++): ~75 ns lookup, 40 ns insert.
  • absl::flat_hash_map: ~25 ns lookup, ~30 ns insert — 3x faster typical wins from open addressing + SIMD probing.
  • folly::F14FastMap: ~30 ns lookup, comparable insert.
  • std::map (RB-tree): ~250 ns lookup — only competitive if you need ordering.
  • boost::container::flat_map (sorted vector): ~40 ns lookup for <100 elements, cache-friendly.
  • std::vector::push_back with reserve: ~3 ns; without: ~6 ns amortized.
  • std::string SBO (libc++ 22-char limit, libstdc++ 15-char limit): zero allocation for short strings.

Use this as a sanity check, not a substitute for measuring your workload with Google Benchmark or nanobench.

Real-world C++ in 2026 — language usage observations

  • Most “modern C++” production code targets C++17 or C++20. C++23 adoption is gated by toolchain support (GCC 14+, Clang 16+, MSVC 19.30+).
  • Modules are real but ecosystem-thin — Boost, Qt, libfmt shipping module interfaces gradually. Most code still uses #include.
  • Concepts (C++20) are widely adopted — readable template errors are too valuable to skip.
  • Coroutines (C++20) have stabilized via cppcoro / folly::coro / Asio integration; everyday usage still niche.
  • Embedded / freestanding code (kernel, firmware) still often C++17 with -fno-exceptions -fno-rtti.
  • Compile-time string parsing (ctre, Frozen) and reflection-via-TMP (boost::pfr, magic_enum) are common workarounds while waiting for C++26 reflection.

Coroutine and ranges examples (C++20+)

Coroutines and ranges are the two biggest C++20 features that change how everyday code looks.

#include <ranges>
#include <vector>
#include <print>
 
int main() {
    std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 
    // Ranges pipeline: lazy view composition
    auto result = nums
                | std::views::filter([](int n) { return n % 2 == 0; })
                | std::views::transform([](int n) { return n * n; })
                | std::ranges::to<std::vector>();  // C++23
 
    for (int x : result) std::print("{} ", x);  // 4 16 36 64 100
}
#include <coroutine>
#include <generator>     // C++23
#include <print>
 
std::generator<int> fibs() {
    int a = 0, b = 1;
    while (true) {
        co_yield a;
        std::tie(a, b) = std::pair{b, a + b};
    }
}
 
int main() {
    int i = 0;
    for (int n : fibs()) {
        if (i++ == 10) break;
        std::print("{} ", n);  // 0 1 1 2 3 5 8 13 21 34
    }
}

std::expected<T, E> (C++23) provides a Rust-Result-like value-or-error:

#include <expected>
#include <string>
 
std::expected<int, std::string> parse(std::string_view s) {
    int n;
    auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), n);
    if (ec != std::errc{}) return std::unexpected("parse failed");
    return n;
}
 
auto result = parse("42")
    .and_then([](int n) -> std::expected<int, std::string> { return n * 2; })
    .transform([](int n) { return n + 1; });   // monadic chaining

C++26 preview (publication 2026)

The C++26 working draft is feature-complete around mid-2025, ISO publication 2026. Headline features:

  • Static reflection (P2996) — ^^T reflection operator, [: e :] splice. Replaces most macro / TMP codegen.
  • Pattern matching (P2688) — inspect expression with structural matching, à la Rust match.
  • std::execution (P2300) — sender/receiver async composition. Subsumes futures + channels + coroutines into a unified model. Major libraries (NVIDIA stdexec, libunifex) shipping reference implementations.
  • Contracts (P2900) — pre, post, contract_assert for design-by-contract; runtime-checked or build-time-erased.
  • std::hazard_pointer, std::rcu (P2530, P2545) — lock-free reclamation for concurrent data structures.
  • std::simd (P1928) — portable SIMD types (parallel to Vector API in Java).
  • Linear algebra (P1673) — BLAS-style operations on mdspan.
  • Networking (proposed for C++26 or 29 — historically slipped) — std::net::ip::tcp, async via senders.
  • constexpr cast from void* (P2738), more constexpr everything.
  • Profiles + Safety profiles (Stroustrup P3081) — opt-in subsets of C++ that disallow UB-prone constructs (pointer arithmetic, casts, etc.) for safer code paths.

The safety profiles work is C++‘s answer to the regulatory and industry pressure (CISA, NSA, White House memos) recommending memory-safe languages. Whether profiles are sufficient or whether Carbon / Rust supplants C++ in greenfield systems work is the open debate of the decade.

Concurrency examples (C++20+)

#include <thread>
#include <mutex>
#include <atomic>
#include <latch>
#include <barrier>
#include <semaphore>
#include <print>
 
// std::jthread auto-joins on destruction + supports cooperative cancellation
void worker(std::stop_token stoken, int id) {
    while (!stoken.stop_requested()) {
        std::print("worker {} alive\n", id);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}
 
int main() {
    std::jthread t1{worker, 1};
    std::jthread t2{worker, 2};
    std::this_thread::sleep_for(std::chrono::seconds(1));
    // t1.request_stop() called by destructor; auto-joined
}
 
// std::latch — one-shot countdown
std::latch ready{4};
auto fn = [&] { ready.count_down(); };
// ... 4 threads call fn ...
ready.wait();  // blocks until count hits 0
 
// std::barrier — reusable, with optional completion fn
std::barrier sync_point(3, [] { std::print("phase done\n"); });
 
// std::counting_semaphore — bound concurrency
std::counting_semaphore<8> slots{8};
auto run_job = [&] {
    slots.acquire();
    do_work();
    slots.release();
};
 
// Atomics with explicit memory order
std::atomic<int> counter{0};
counter.fetch_add(1, std::memory_order_relaxed);   // for counters
counter.store(0, std::memory_order_release);       // pairs with...
auto v = counter.load(std::memory_order_acquire);  // ...this

Coroutines + Asio is the modern async I/O recipe; awaitables on sockets compose cleanly:

asio::awaitable<void> echo(asio::ip::tcp::socket sock) {
    char data[1024];
    try {
        for (;;) {
            auto n = co_await sock.async_read_some(asio::buffer(data), asio::use_awaitable);
            co_await asio::async_write(sock, asio::buffer(data, n), asio::use_awaitable);
        }
    } catch (std::exception&) { /* client closed */ }
}

Sanitizer matrix (when to use what)

SanitizerCatchesOverheadWhen
AddressSanitizer (ASan)Use-after-free, OOB, double-free, leaks2-3x runtime, 2-3x memoryAll test runs, dev builds
UndefinedBehaviorSanitizer (UBSan)Signed overflow, alignment, null deref, invalid casts~10%All test runs
ThreadSanitizer (TSan)Data races5-15x, 5-10x memoryConcurrency tests
MemorySanitizer (MSan)Uninitialized reads3xRequires recompiling all libs incl. libc++
LeakSanitizer (LSan)Memory leaks at exitminimalBundled with ASan by default
HWAddressSanitizer (HWASan)Like ASan but lower memory (AArch64)2x runtime, 1.1x memoryProduction fuzzing on ARM
DataFlowSanitizer (DFSan)Taint trackinghighSecurity analysis
CFI (Control Flow Integrity)Indirect-call type confusion~5%Hardened production builds (Chromium, Android)

CI typically runs ASan + UBSan on every PR, TSan on a subset, MSan rarely. Production builds use CFI + stack protectors.

C++20 modules — complete working example

The fragmented world of #include is finally addressable. A full minimal project demonstrating module interface unit + module partition + named module + import std:

math.cppm (module interface unit — declares the math module):

// math.cppm
export module math;
 
export import :geometry;     // re-export a partition
 
import std;                  // C++23 std module
 
export namespace math {
    constexpr double square(double x) { return x * x; }
    export double sum(std::span<const double> xs) {
        double s = 0;
        for (auto x : xs) s += x;
        return s;
    }
}

math-geometry.cppm (module partition — internal to math):

// math-geometry.cppm
export module math:geometry;
 
import std;
 
export namespace math {
    struct Point { double x, y; };
    export double distance(Point a, Point b) {
        return std::hypot(a.x - b.x, a.y - b.y);
    }
}

main.cpp (consumer):

import std;
import math;
 
int main() {
    std::vector v{1.0, 2.0, 3.0};
    std::println("sum = {}", math::sum(v));
    std::println("dist = {}", math::distance({0,0}, {3,4}));
}

CMakeLists.txt (CMake 3.30+ with FILE_SET CXX_MODULES):

cmake_minimum_required(VERSION 3.30)
project(modules_demo CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)   # P1689 module dependency scan
 
add_library(math)
target_sources(math
    PUBLIC FILE_SET CXX_MODULES FILES math.cppm math-geometry.cppm
)
target_compile_features(math PUBLIC cxx_std_23)
 
add_executable(app main.cpp)
target_link_libraries(app PRIVATE math)

Compiler flags by vendor (2026 reality):

  • Clang 19+: -std=c++23 -fmodules -fbuiltin-module-map. BMI files emitted as .pcm. Production-ready as of 18+.
  • GCC 14+: -std=c++23 -fmodules-ts (legacy spelling) / -fmodules (15+). BMI as .gcm. Partial — module partitions stabilizing in 15.
  • MSVC 19.30+ (VS 2022 17.x): /std:c++latest /experimental:module (early) → /std:c++20 /module (modern). BMI as .ifc. Production-ready in 17.4+.
  • Ninja 1.11+ required for the dynamic dependency protocol (P1689 / JSON provides/requires).

Header units bridge legacy #include into the module world:

import <vector>;        // header unit — translated to BMI, faster than #include
import <string>;

These produce per-header BMIs but don’t isolate macros — they’re a migration bridge, not the destination.

Real-world cross-language interop

C++ is the lingua franca of native FFI. The 2024-26 toolchain has stabilized around a few clear winners per language:

C++ ↔ Rust (cxx + autocxx) — type-safe, bidirectional, used in Chromium, Servo, R4L:

// build.rs uses cxx-build
#[cxx::bridge]
mod ffi {
    extern "Rust" {
        fn rust_compute(x: i32) -> i32;
    }
    unsafe extern "C++" {
        include!("myapp/cpp_lib.h");
        fn cpp_render(data: &CxxString) -> i32;
    }
}
fn rust_compute(x: i32) -> i32 { x * 2 }

autocxx (Google) auto-generates the bridge from C++ headers via libclang; the dev workflow is #include "header.h" then include_cpp! { #include "header.h" generate!("MyClass") }. Production at Google for Chromium UI components, Firefox’s stylo CSS engine. libloading covers the dlopen/LoadLibrary case when you don’t have headers.

C++ ↔ Python (pybind11, nanobind, Cython, cffi):

ToolStyleBinary sizeCompile timeWhen
pybind11Header-only, declarativebaselinebaselineMature C++ Python bindings; PyTorch, OpenCV, Pinocchio use it
nanobindHeader-only, ABI-stable Python (3.8+)4x smaller6x fasterNew projects; Wenzel Jakob (same author as pybind11)
Cython.pyx Python-superset compiled to Cmediumslow (full C compile)numpy, scikit-learn, sage; when you control both sides
cffiRuntime C ABI bindingsmallnonePure-C libs, when you don’t want a build dep
cppyyJIT via Cling (LLVM)runtime costnoneInteractive / data science (CERN ROOT)

Minimal pybind11 + nanobind comparison:

// pybind11
#include <pybind11/pybind11.h>
PYBIND11_MODULE(mymod, m) {
    m.def("add", [](int a, int b) { return a + b; });
}
 
// nanobind — visually identical, 4x smaller .so, 6x faster compile
#include <nanobind/nanobind.h>
NB_MODULE(mymod, m) {
    m.def("add", [](int a, int b) { return a + b; });
}

Build both with scikit-build-core or meson-python + pyproject.toml.

C++ ↔ WebAssembly (emscripten, Cheerp):

  • emscripten — the dominant choice; LLVM-based, includes wasm-ld, Asyncify for sync APIs over async JS, file-system emulation (MEMFS, IDBFS, NODEFS). Use cases: AutoCAD Web, Figma rendering engine, Photoshop Web, Google Earth, Unity WebGL builds, Unreal HTML5.
em++ -std=c++23 -O2 -sWASM=1 -sEXPORTED_FUNCTIONS='["_main","_compute"]' \
    -sMODULARIZE=1 -sEXPORT_ES6=1 main.cpp -o main.mjs
  • Cheerp — alternative LLVM-based, dual-target (compile parts to JS, parts to WASM, share types). Used at Leaning Technologies (CheerpJ for Java→WASM, CheerpX for x86→WASM, including running entire Windows binaries in browser).

WASI Preview 2 + Component Model (wasi-sdk + wit-bindgen) is the path to portable C++ components running on Wasmtime, Spin, Fastly Compute@Edge, Cloudflare workerd, WasmEdge.

10. Citations