const & constexpr Basics
Some values should never change: a tax rate, the number of squares on a chessboard, pi. Marking them const tells the compiler to reject any accidental reassignment, and constexpr goes further by computing values at compile time. "Const-correctness" — using const everywhere you can — is one of the habits that separates solid C++ from buggy C++. This lesson makes it second nature.
Learn const & constexpr Basics in our free C++ course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Think of const as writing a value in permanent ink instead of pencil — you can read it forever, but you can't erase and rewrite it. constexpr is stronger still: it's like a value engraved into the building's cornerstone before the doors even open — fixed at construction time (compile time), so it can be used as part of the structure itself, such as deciding how many rooms (array slots) to build. Both protect you: if you (or a teammate) ever try to change something that was meant to be fixed, the compiler stops you immediately instead of letting a subtle bug slip through.
Rule of thumb: use const by default for anything you don't intend to change; promote to constexpr when the value is a fixed compile-time constant.
1. const: Read-Only Values
Add const before a type and the variable becomes read-only: you must initialize it on the spot, and any later attempt to reassign it is a compile error . This is a feature, not a restriction — it documents intent ("this never changes") and lets the compiler catch accidental writes. By convention, constants are named in UPPER_SNAKE_CASE .
2. constexpr: Compile-Time Constants
constexpr is a promise that a value can be computed at compile time . That unlocks uses where C++ requires a compile-time constant — most notably the size of a fixed array or a . Every constexpr is implicitly const , but it adds the stronger guarantee of compile-time evaluation.
Your turn. Choose the right keyword for each constant — one needs to size an array (so it must be compile-time):
These lines use a constexpr size to build and fill an array. Put them in order:
Open main (C), declare the constexpr size first (B), use it to size the array (A), fill it (D), print data[3] = 3 (E), then return 0; (F) and close (G). N must be a compile-time constant declared before it sizes the array.
3. const References in Parameters
A huge practical use of const is in function parameters. Passing a large object by value copies it; passing by const& hands over a reference (no copy) while promising the function won't modify it. This pattern — const std::string& , const std::vector<T>& — is everywhere in good C++ code: fast and safe.
4. const Member Functions
A member function with const after its parameter list promises not to modify the object it's called on. Getters are the classic example. The payoff: a const object may only call const member functions, so marking your read-only methods const lets them work on constants and documents that they don't mutate state.
A constexpr function is one the compiler can evaluate at compile time when its arguments are themselves constant. The same function still works at run time when given runtime values — you write it once and get both:
Computing values at compile time means zero runtime cost and lets results be used where the language demands a constant. In C++20, consteval forces compile-time evaluation, and constinit guarantees compile-time initialization of globals.
Predict the output (or whether it compiles) before revealing the answer.
No — LIMIT is const , so LIMIT = 10; is an error: "assignment of read-only variable".
In standard C++, int arr[n]; with a non-const n is not allowed (variable-length arrays aren't standard). int brr[m]; with constexpr m is fine — it's a compile-time constant.
Yes — prints 7 — get() is a const member function, so a const object may call it.
Put a constexpr constant and const-correct functions together to compute a circle's area and circumference.
Practice quiz
What does 'const' do to a variable?
- Makes it global
- Forces compile-time evaluation
- Marks it read-only so it cannot be reassigned after initialization
- Makes it faster
Answer: Marks it read-only so it cannot be reassigned after initialization. const is read-only once set; any attempt to reassign it is a compile error.
What is the key difference between const and constexpr?
- constexpr requires a value computable at compile time; const may be computed at run time
- No difference
- const is compile-time, constexpr is run-time
- constexpr can be reassigned
Answer: constexpr requires a value computable at compile time; const may be computed at run time. Both can't be reassigned, but constexpr guarantees compile-time evaluation; const only guarantees read-only.
Which can be used as the size of a fixed-size array?
- Any const
- Any runtime int
- Only literals
- A constexpr value (or a const that is itself a compile-time constant)
Answer: A constexpr value (or a const that is itself a compile-time constant). Array sizes require a compile-time constant; constexpr guarantees this.
Why pass a large object by const reference (const T&)?
- To copy it safely
- To avoid copying while promising not to modify it
- To make it mutable
- To force compile-time evaluation
Answer: To avoid copying while promising not to modify it. const& gives the speed of passing by reference (no copy) and the safety of read-only access.
What does marking a member function 'const' (after its parameter list) promise?
- It will not modify the object it is called on
- It returns a const value
- It is evaluated at compile time
- It is private
Answer: It will not modify the object it is called on. A const member function promises not to mutate the object, so const objects may call it.
A const object can call which member functions?
- Any member function
- Only static functions
- Only const member functions
- None
Answer: Only const member functions. A const object may only call const member functions, which is why getters should be marked const.
Does 'const int LIMIT = 5; LIMIT = 10;' compile?
- Yes
- No — 'assignment of read-only variable'
- Only with -std=c++20
- Only if LIMIT is global
Answer: No — 'assignment of read-only variable'. Reassigning a const is a compile error.
Can a single constexpr function be called at run time too?
- No, never
- Only if marked inline
- Only with consteval
- Yes — it runs at compile time when its arguments are constant, and at run time otherwise
Answer: Yes — it runs at compile time when its arguments are constant, and at run time otherwise. A constexpr function works in both modes depending on whether its arguments are compile-time constants.
Why does 'constexpr int x = readInput();' fail to compile?
- readInput is private
- The initializer must be a constant expression, but a runtime value isn't known at compile time
- constexpr needs a double
- x must be const
Answer: The initializer must be a constant expression, but a runtime value isn't known at compile time. constexpr demands a compile-time-known initializer; use plain const for a runtime value.
Every constexpr variable is also:
- static
- inline
- const
- volatile
Answer: const. constexpr implies const and adds the stronger guarantee of compile-time evaluation.