ReviseAlgo Logo

Basic Syntax

Constants and Literals

const, constexpr, and literal types

Interview: Modern C++ practices

Constants and Literals in C++

Modern C++ distinguishes heavily between runtime constants and compile-time constants. Evaluating expressions at compile time is a core optimization paradigm, allowing applications to minimize runtime footprint and overhead.

Const vs. Constexpr vs. Consteval

const (Runtime Const)

Promises that a variable cannot be modified after its initialization. The initialization value itself can be resolved at runtime (e.g., reading user inputs: const int input = readFromUser();).

constexpr (Compile-time Const)

Introduced in C++11. Indicates that the variable or function value is evaluated at compile time. It is implicitly const. Must be initialized using constant expressions.

consteval (Immediate Functions)

Introduced in C++20. Declares that a function must evaluate at compile time. It guarantees that no runtime function call instruction is generated. Calling a consteval function with a non-constant parameter is a compile-time error.

constinit (Global Constant Init)

Introduced in C++20. Guarantees that global variables are initialized at compile-time to prevent static initialization order fiasco (SIOF). Note: the variable itself remains modifiable at runtime.

Literals, Suffixes, and User-Defined Literals

C++ supports visual literal formatters like digit separators (1'000'000), binary literals (0b101010), and literal suffixes (ULL for unsigned long long, f for float). Advanced developers can define User-Defined Literals (UDL) to attach type meaning to raw suffixes (e.g. converting 3.4_km directly to meters).

Interview Corner

Q: What is the difference between const and constexpr?

A: const represents a read-only variable whose value is determined either at compile-time or runtime. constexpr is evaluated strictly at compile-time, allowing its value to be used as array sizes, template parameters, or case labels.

Q: What is the static initialization order fiasco (SIOF), and how does constinit solve it?

A: SIOF happens when a global variable in one translation unit depends on another global variable in another unit before it has been initialized. C++20's constinit guarantees that global constant expressions are fully initialized during compilation, eliminating SIOF initialization race conditions.

Common Pitfalls

  • Assuming const is compile-time: Trying to declare array sizes using runtime constants: int x; cin >> x; const int sz = x; int arr[sz]; (leads to VLA compilation errors on strict compilers).
  • Overcomplicating constexpr functions: Writing functions with infinite recursion or massive loops. If compilation limits are exceeded, compilation errors will occur.

Best Practices

  • Make variables constexpr whenever their values are fully known at compile-time.
  • Use digit separators 1'000'000 to format large integers for code readability.
  • Avoid old C-style preprocessor #define constants; they have no type checking and ignore scope constraints.

Use Cases

Compile-Time Tables: Pre-computing sine tables, cryptographical lookup maps, or string hashes during compiling.

Self-Documenting Types: Creating physical representations in code using UDL suffixes (e.g. `_seconds`, `_px`).

Zero-Cost Maths: Computing factorials or complex algorithm parameters prior to deployment.

Common Mistakes

Confusing const with constexpr and using it in static array limits.

Calling non-constexpr processes inside a constexpr context.

Assuming constinit generates variables that are immutable.