Skip to content

Appendix E — Glossary

Appendix E — Glossary

The book uses these terms in the ordinary course of explaining things, the way your future colleagues will — which is precisely why they need one page. Each entry is a sentence or two and a pointer to the chapter where the idea actually lives; the definition here is for recognition, the chapter is for understanding. Two groups: terms this book uses, then terms you will merely hear — review comments and hallway conversation use them without introduction, and knowing which kind of thing each one is beats nodding along. If what you have is a symptom rather than a term — a report, an error message, a wrong number — the other half of this appendix is Chapter 31's symptom index.

Terms this book uses

  • ABI (application binary interface) — the compiled contract between binaries: struct layouts, calling conventions, mangled names — everything your compiler chose rather than you wrote. In C#, IL and metadata made this someone else's problem; Chapter 30 is about authoring one on purpose, and an ABI break is a change to any of it that forces every consumer to rebuild.
  • abstract syntax tree (AST) — the tree a parser builds from text, one node per operator, value or call, evaluated by walking it; in this book a closed set of node kinds as a std::variant, with the children behind unique_ptr because a node cannot hold a node by value (a std::vector of nodes is the same indirection with a count). Chapter 42.
  • acquire / release (memory orders) — the two std::memory_order values that make a hand-off correct: a store tagged release makes every write before it visible to a thread whose acquire load reads the stored value. The default, seq_cst, is stronger and correct; relaxed is no ordering with respect to anything else, and a ring that publishes with it delivers stale slots on arm64. C#'s volatile read and write are this pair under the CLR's names. Chapter 43.
  • assert / NDEBUGassert(cond) dies loudly in Debug builds and compiles to nothing when NDEBUG is defined (the usual Release default) — so it documents a contract, never handles a failure. The bug pole of Chapter 8's bug/value/event decision.
  • blittable — a type whose managed and native representations are identical, so the marshaller has nothing to translate and the bytes cross as they are, pinned and passed by address where the call takes one: fixed-width integers, floats, pointers, and structs made only of those. bool, char and string are not, and one non-blittable field makes the whole struct a copy. Chapter 39.
  • capacity vs size — a vector's size() is the elements that exist and capacity() the room allocated for them. reserve grows the second without constructing anything; resize and the vector(n) constructor grow both. Growth past capacity is Chapter 11's reallocation, and Recipe 27 in Appendix F is the List<T>(capacity) mapping.
  • const-correctness — marking every member function and parameter that does not modify what it is given, so a const& reaches only the read half of a type. Enforced entirely at compile time, transitive, and nearly free at the start of a class where it is expensive to retrofit later. C#'s readonly protects a field; this protects a route. Appendix I.
  • context pointer (user-data pointer) — the void* a C API stores alongside your callback and hands back on every call: your closure state, threaded through by hand, recovered by a trampoline — the static function that casts it back to your object and forwards. Chapter 18 builds the pattern; every callback-based C SDK is wrapped this way.
  • copy-and-swap — the assignment idiom: do all the throwing work in a local copy, then swap it into place with a few noexcept pointer exchanges. Strong exception guarantee and self-assignment safety fall out structurally. Chapter 6, applied in Chapter 15.
  • dangling pointer / dangling reference — one that points at storage whose lifetime has ended: a dead stack frame, a freed block, a reallocated buffer. Reading through it is UB, not an error message. Chapter 3.
  • declaration vs definition — a declaration is the promise (void f(int); — this exists somewhere); the definition is the thing itself. Headers carry declarations so every translation unit can see them; exactly one TU carries each definition. Chapter 12.
  • decltype — "the type this expression has", answered by the compiler with no runtime involved: decltype(&Device_SetCallback) names a vendor function-pointer type without retyping it. C# has no counterpart — typeof is a runtime object, and var is only the auto half. Chapter 10.
  • endianness — the byte order of multi-byte values in memory: little-endian hosts store the low byte first, network order is big-endian, and a value read in the wrong order is its own mirror image. Chapter 34.
  • extern "C" — switches off C++ name mangling for a function so C — and C#'s P/Invoke — can find the symbol by its plain name. The spelling of every plug-in entry point and C API boundary. Chapter 12 for the mechanism, Chapter 30 for the façade built from it.
  • false sharing — two variables written by two threads that happen to share one cache line, so each write invalidates the other core's copy and two threads touching two different variables pay for a shared one. Never appears in a profile as itself; the fix is alignas and padding, and the number to pad by is a decision. Appendix L, applied in Chapter 43's ring.
  • feature flag — a behavior decided by configuration, not code: read once at startup into a member and tested with if — Recipe 31 in Appendix F. The first, and the only build-free one, of Chapter 26's four switches; that chapter owns the other three and the hazard C# cannot express, a switch that changes a type's layout.
  • feature-test macro — a macro the compiler (__cpp_if_constexpr) or the standard library (__cpp_lib_optional, through <version>) defines once it implements a feature, valued as the year and month of the feature's current shape. The honest way to ask whether a feature is there — __cplusplus names the standard the compiler was told to speak, and the library ships behind it. Appendix K, with the probe that prints them.
  • forwarding reference / std::forwardT&& where T is a function template's own parameter, deduced from that very argument: it binds to lvalues and rvalues alike, and std::forward<T>(x) passes the argument on as it arrived — an lvalue still borrowed, an rvalue still stealable — where std::move would gut the caller's variable. Chapter 6's coda draws the line against the plain rvalue reference; Chapter 8's Result constructor and Recipe 28 in Appendix F are the two the book writes.
  • header / include guard#include is textual paste, so a header must survive being pasted twice; #pragma once (or the classic #ifndef guard) is what makes that safe. Chapter 12.
  • header-only library — a dependency that ships as headers alone: nothing to link, no separately compiled code whose ABI must match yours, which is why the ecosystem loves the form. Chapter 27.
  • ICD (interface control document) — the document that owns a wire or bus format: fields, widths, offsets, byte order. When bytes disagree with a struct, the ICD is the side that is right. Chapter 34.
  • interrupt context (ISR, driver context) — code that runs on whatever the processor was doing when the interrupt arrived, to completion, with no thread of its own and no context pointer: it cannot block on anything, because what it would wait for is the code it interrupted; everything it touches must exist before main, and nothing it touches may take a lock. A POSIX signal handler is the desktop's version, under the same rules. Chapter 16's Shape 4, paid in Chapter 43.
  • iterator invalidation — a container mutation voiding iterators, pointers, and references into that container; vector growth is the canonical case. Chapter 11 has the rules per container, Chapter 21 the lab, Chapter 33 the ticket it becomes at work.
  • lvalue / rvalue — roughly: something with a name and an address, versus a temporary about to expire. The distinction decides copy versus move — an rvalue's guts may be stolen because nobody can observe the theft. The third word you will meet, xvalue, is an lvalue that std::move has marked expiring: same object, permission granted. Chapter 6's table has all three.
  • marshalling — converting a value between its managed and native representations at a boundary: encoding a string, widening a bool, copying a struct field by field. Free when both sides are blittable, and the source of the mojibake in Chapter 9 when they disagree about encoding.
  • memory-mapped file / shared memory — a region of memory two processes see at once, named on POSIX (shm_open + mmap) or on Windows (CreateFileMapping + MapViewOfFile); what goes in it is a wire format, since the other process has its own compiler and its own address space, and the name outlives every process that mapped it until someone unlinks it. Appendix G prices the lane; Recipe 43 in Appendix F builds it.
  • move semantics / std::move — transferring a resource instead of copying it, leaving the source valid-but-empty. std::move performs no move: it is a cast that marks its argument movable-from. Chapter 6.
  • mutable — a member excluded from its object's value, so a const member function may write it: caches, memo tables, and the mutex you must lock in order to read safely. Appendix I.
  • name mangling — the encoding of a function's name, namespace and parameter types into the linker symbol (_ZN6Engine7ProcessEi), which is how C++ overloads coexist in a format designed for C. Chapter 12.
  • noexcept — a promise that a function cannot throw — and a promise the standard library reads: vector will move your elements during reallocation only if the move constructor is noexcept, else it copies. Chapter 6.
  • ODR (One Definition Rule) — every entity gets exactly one definition across the whole program. Violations — two versions of one library, a class defined differently in two TUs — need no diagnostic and often produce none. Chapter 12, and Chapter 27's diamond problem.
  • opaque handle — a pointer to a type the header declares but never defines (typedef struct Device_* DeviceHandle;): the C API's encapsulation, because a caller cannot touch what it cannot see the layout of. Chapter 16's Shape 2, worked in Chapter 18.
  • out-parameter — a result delivered through a pointer argument (GetData(id, &data)), leaving the return channel free for a status code. The C-API idiom C# spells out. Chapter 16.
  • ownership (owner / borrow / view) — who is responsible for releasing a resource, and for how long everyone else may look at it. An owner releases — a stack object, a unique_ptr, a guard; a borrow is a reference or raw pointer valid for a stated term; a view is a borrow of a buffer, string_view or span. The word every signature answers to in Appendix H, and Chapter 33's "loan" is a borrow with its term written down. Chapter 1.
  • padding / alignment — the invisible bytes a compiler inserts between members so each sits at an address its type requires; the reason sizeof a struct is not the sum of its parts, and the first of Chapter 34's three bugs.
  • parent ownership (a framework's object model) — a C++-native framework's lifetime rule: an object constructed with a parent belongs to the parent, which deletes it in its own destructor, at the moment the framework chooses; one without a parent is yours. A unique_ptr on a parented object is a second owner. Chapter 16's Shape 5, worked as a ticket in Chapter 44.
  • PIMPL (pointer to implementation) — a class whose only member is an opaque pointer to its real state, so the public header exposes no layout at all and the implementation may change without an ABI break. Chapter 30.
  • P/Invoke (platform invoke) — .NET's mechanism for calling a native extern "C" function: a [DllImport] or [LibraryImport] declaration that restates your signature in C#, by hand, checked by nothing on either side. Chapter 39 is the same boundary seen from the half you publish.
  • priority inversion — a high-priority thread waiting on a lock held by a low-priority one that the scheduler has preempted, so the important thread's wait lasts as long as the scheduler's disinterest in the unimportant one. The reason a mutex is forbidden on a deadline path. Chapter 43.
  • RAII (Resource Acquisition Is Initialization) — the founding idiom: a resource's lifetime is an object's lifetime, acquisition in the constructor, release in the destructor, and the destructor is guaranteed — early return, exception, any exit. C#'s using made structural and universal. Chapter 1.
  • recursive descent — a parser written as one function per grammar rule, each calling the rules below it, so precedence is the call order and associativity is a loop; the recursion is as deep as the text, which is why it is bounded. Chapter 42.
  • reference counting (refcounting) — shared ownership by counter: every acquisition is a debt, every release a payment, and the object dies at zero. COM's model, Chapter 16's Shape 3, debugged as a ticket in Chapter 35.
  • retrofit (source compatibility vs behaviour compatibility) — changing the insides of a class whose surface other people compiled against. The surface is every declaration a caller can name and every promise the old implementation kept without saying so — an address that stays valid, an operation that adds nothing on failure. Source that still compiles is checked by the build; behaviour is checked by the unchanged caller's output under the sanitizers. When the callers cannot recompile, the surface includes the layout and the retrofit stops at Chapter 30's boundary. Chapter 45.
  • Rule of Zero / Three / Five — how many special member functions a class must define: five if it owns a raw resource (destructor, two copies, two moves), zero if its members own everything for it — and zero is the goal. Chapter 6.
  • RVO / NRVO ((named) return value optimization) — the compiler constructs a returned local directly in the caller's storage, eliding the copy/move entirely; guaranteed for temporaries since C++17, permitted-and-usual for named locals. Chapter 14 watches it happen.
  • sanitizers (ASan, UBSan, TSan, LSan) — compiled-in bug detectors: AddressSanitizer for memory errors, UndefinedBehaviorSanitizer for UB with a defined signature, ThreadSanitizer for data races (its own build — it does not combine with ASan), LeakSanitizer for leaks (platform-dependent: absent on macOS/arm64). Development-only; the flags are in Chapter 13, reading their reports is Chapter 31.
  • seam (of a retrofit) — the unit of change in a modernisation: one declaration or one member's storage, small enough that when the unchanged caller's output changes there is one thing it could have been, and each green under the flags before the next. Declare the special members, move the ownership inside, let the destructor go, earn the copy — in that order. Chapter 45.
  • single-producer, single-consumer queue (SPSC ring) — a fixed ring of slots with two atomic indices, each written by exactly one thread, so no lock is needed and the only question is visibility, which two memory orders answer. The hand-off to a deadline thread, and out of an interrupt handler; the general multi-producer case is a different structure and, in this book, someone else's library. Chapter 43.
  • slicing — assigning or passing a derived object by value as its base copies only the base part; the derived half is cut off silently, virtuals included. Impossible in C#, routine here. Chapter 2, the lab in Chapter 20.
  • smart pointers (unique_ptr, shared_ptr, weak_ptr) — ownership as types: sole ownership that moves, shared ownership that counts, and a non-owning observer that can ask "still alive?". The everyday spelling of Chapter 1.
  • static initialization order fiasco — namespace-scope objects in different translation units are constructed in an order the language does not specify, and destroyed in reverse of it — so cross-TU use during startup or shutdown is a bet. Chapter 32 is the ticket it files.
  • stack overflow — a frame that does not fit the thread's stack, which Chapter 3 sizes per platform: a local, or a member of a local, of megabytes. The crash is on entry to the function, and AddressSanitizer names it stack-overflow only when the fault lands within 64 KB of the stack pointer and a bare SEGV/BUS otherwise — not stable, even between runs — none of Chapter 31's four shapes either way. Recipe 34 in Appendix F puts the object behind a unique_ptr.
  • strict aliasing — the rule that memory of one type may not be read as another (narrow exceptions aside), which makes the tempting cast-a-buffer-to-a-struct overlay illegal even on days it appears to work. Chapter 34.
  • thread affinity — the requirement that an API be used only from one particular thread — usually the owner's main/UI thread — stated (or omitted) by documentation and enforced by nothing. C# handed you the cure ready-made as Dispatcher and SynchronizationContext; Chapter 29 names the constraint, and Chapter 38 builds the queue that honours it when foreign code must drive the host.
  • tokenizer (lexer) — the pass that turns bytes into tokens — numbers, names, operators — each carrying the offset it began at, so every later error can point at a character. Chapter 42.
  • translation unit (TU) — one .cpp file after preprocessing: the compiler's actual unit of work, compiled in isolation and linked later. Most of Chapter 12's surprises are consequences of that isolation.
  • UB (undefined behavior) — the contract's void: for certain operations the standard promises nothing, so the program may crash, corrupt, or — worst — look correct today. Not an error you catch; a state you must not enter. Chapter 3.
  • unwinding (stack unwinding) — the destructor-running walk from a throw toward its handler. No handler means no unwind: an uncaught exception terminates without running destructors. Chapter 8.
  • value semantics — assignment and pass-by-value copy the object itself, not a reference to it; every type behaves like a C# struct unless you say otherwise. Chapter 2.
  • variant (std::variant) — a value that is exactly one of a fixed list of types, with the tag enforced: the kind-plus-union of every vendor event struct made safe, and switched on with std::visit, which refuses a visitor that forgets an alternative. The closed-set alternative to a virtual hierarchy. Chapter 10.
  • volatile — "this memory may change outside the program": for memory-mapped hardware registers. It is not C#'s volatile — no atomicity, no ordering, not a threading tool; that job belongs to std::atomic. Chapter 29.
  • vtable / virtual dispatch — the per-class table of function pointers behind virtual, reached through a hidden pointer in each polymorphic object; also why a base without a virtual destructor deletes wrongly through a base pointer. Chapter 5.
  • weak handle (a framework's own) — the observer type a framework ships for objects it owns: it reads null once the object is gone and never keeps it alive — QPointer, TWeakObjectPtr, the lab's NodeRef. weak_ptr with the framework where the control block was; the pointer you are allowed to hold to what is theirs. Chapter 44.

Terms you will hear

None of these is taught in this book — each is either a deeper-water idiom or a historical term still in circulation. The entries are for recognition, so a review comment lands as information rather than fog.

  • ADL (argument-dependent lookup) — an unqualified function call also searches the namespaces of its arguments' types; the mechanism that lets swap(a, b) and operators find the right overload without qualification. Mostly invisible until it surprises you; then it has a name.
  • CRTP (curiously recurring template pattern) — a class deriving from a template instantiated with itself (class D : Base<D>): compile-time polymorphism with no vtable. Common in performance-minded libraries; recognize the shape and read the base. Chapter 41 says why it stays untaught.
  • inline namespace — a nested namespace marked inline, whose members are reachable as if they were in the parent while the mangled symbol still carries the nested name. The C++-name way to ship two versions of one library at once: source says acme::Session, an old binary keeps calling the version it was built against. libstdc++'s std::__cxx11 is the one you will meet. Chapter 12, Chapter 30.
  • linkage (internal / external) — whether a name is visible to other translation units. static at namespace scope (or an anonymous namespace) makes it internal — private to its TU; external is the default for functions and globals. The vocabulary for Chapter 12's model, used heavily in linker-error conversations.
  • POD ("plain old data") — the old word for "safe to memcpy, layout like C". Officially retired in favour of two precise properties — trivially copyable and standard-layout — but colleagues and older docs still say POD; the layout rules it gestures at are Chapter 34's territory.
  • SFINAE (substitution failure is not an error) — the pre-C++20 machinery for constraining templates: an overload whose substitution fails silently drops out of consideration. You will meet it in older library code and error messages; its modern successor is C++20 concepts (Chapter 7 shows those as C#'s where, fifteen years late). The one use this book makes of it is the detection idiom in Chapter 41.