Variables — types, initialization, ownership
A variable is a named region of memory with a type, a value, and a lifetime. C++ gives you explicit control over all three: you decide how many bytes the object occupies, how it is initialized, whether it can be modified, how long it lives, and where its name is visible.
This is not pedantry for its own sake. Picking int over int32_t, forgetting to initialize, mixing up const T* vs T* const, or confusing static (linkage) with static (storage duration) are sources of real bugs. References, templates, and move semantics all sit on top of these basics — you cannot move on without them.
Topic map
- Data types —
int/float/char/bool, static arrays, overflow UB. - Initialization — forms (
=,(),{}), brace-init and narrowing, UB on read. - const qualifiers —
conston types, pointers, methods;mutable. - const vs constexpr — runtime read-only vs compile-time constant.
- Value categories — lvalue/rvalue and reference binding.
- auto and type deduction —
auto, structured bindings, CTAD. - Bitwise operations — operators, bit fields, shift UB.
- References and pointers — when to use which.
- Scope and linkage — block/namespace/class scope, external/internal linkage, ODR.
- Storage duration — automatic/static/thread/dynamic, magic statics, fiasco.
- Struct layout — padding,
alignas,offsetof, POD/standard-layout/trivially-copyable.
Common traps
| Mistake | Consequence |
|---|---|
int x; without init, then read | UB — the compiler may generate anything |
int x{3.14} expecting truncation | Compile error — brace-init forbids narrowing |
int s = -1; if (s < unsigned(1)) | false — signed converted to a large unsigned |
Comparing double with == | Accumulated rounding error — use an epsilon |
INT_MAX + 1 or shifting by the type width | UB on signed overflow / shift |
Confusing const int* vs int* const | Won't compile, or modifies the wrong thing |
auto x = getRef() expecting a reference | Copy; use auto& or decltype(auto) |
| Global in TU1 depends on a global in TU2 | Static initialization order fiasco — UB |
static int x; in a header without inline | One copy per TU — usually not what you want |
if (x & MASK == 0) without parens | Parses as x & (MASK==0) — precedence bug |
| Struct fields in random order | Extra padding, larger sizeof than necessary |
Interview relevance
Types and initialization are among the most common topics in C++ interviews. The interviewer is not checking syntax memorization — they are checking mechanism — why things are the way they are.
Typical checks:
- Brace-init vs copy-init: why
int x{3.14}does not compile butint x = 3.14does (narrowing). - Uninitialized variables — UB, not "just garbage".
const T*vsT* const— two different things; reading complex declarations.- lvalue/rvalue — the foundation of move semantics and perfect forwarding.
- Signed overflow — UB and how the compiler exploits it for optimization.
intis not always 32 bits — the standard guarantees only ≥ 16 bits; useint32_t.staticin three senses: linkage, storage duration, class member.- Static initialization order fiasco — why globals across TUs are dangerous.
Common wrong answer: "int is always 4 bytes." The standard only guarantees sizeof(int) >= sizeof(short) >= sizeof(char) and a minimum of 16 bits for int. Good C++ expresses requirements explicitly (int32_t, size_t) instead of relying on platform defaults.