C++ Part I · Module 3 · Types, Variables, and Initialization
const and Immutability
Every declaration so far has said what kind of thing an object is. This chapter adds a second thing a declaration can say: that the object will not change after it is created. That sounds like a comment, and the difference between const and a comment is the entire point. A comment is a message to a human being, it is never checked, and it goes out of date the first time somebody edits the code without reading it. const is the same message written in a form the compiler reads, and it fails the build the moment any line contradicts it. That makes it the first example of something this language does repeatedly and does well — letting you state an intention in a way that is verified rather than hoped for. The chapter is deliberately narrow: const appears in several other contexts later, each with its own chapter, and this one is about objects.
Foundation13 min readC++Part IFundamentalsconst
Part I · Module 3 · Chapter 3.9 · const and Immutability
1. A Declaration Can Say More Than the Type
Two declarations of the same kind of thing:
int cycle_count = 19; // may change
const int setup_cycles = 3; // will not changeBoth create an object holding a whole number. The second adds a promise: this object's value will not be modified after it is initialized.
The word is const, short for constant. It is not a different type of number — setup_cycles is still an int — it is a qualifier on the object saying what may be done with it.
2. The Difference From a Comment
You could express the same intention without const:
int setup_cycles = 3; // do not modify thisThat line and the const line communicate the same thing to a human reader. Here is what separates them:
| A comment | const | |
|---|---|---|
| Read by | People, if they look | The compiler, always |
| Checked | Never | On every line that touches the object |
| When it is wrong | Nobody finds out | The build fails |
| After six months of edits | Possibly a lie | Still true, or the code does not compile |
The last row is the one that matters. A comment describes what the code did on the day it was written. const describes what the code does now, because it cannot stop being true without the build breaking.
Try to break it and see:
int main()
{
const int setup_cycles = 3;
setup_cycles = 4; // INCORRECT
return setup_cycles;
}constbad.cpp:4:18: error: cannot assign to variable 'setup_cycles'
with const-qualified type 'const int'Not a warning — an error. The promise is enforced.
constturns a statement of intent into a constraint the compiler checks. That is the whole feature.
3. A Working Example
#include <cstdint>
#include <iostream>
int main()
{
const std::uint32_t register_base = 0x4000'0000u;
const int setup_cycles = 3;
std::cout << "register_base = " << register_base << '\n';
std::cout << "setup_cycles = " << setup_cycles << '\n';
return 0;
}Expected output:
register_base = 1073741824
setup_cycles = 3Both are values that come from a specification rather than from the program's logic. The base address of a peripheral is fixed by the hardware. The setup cost of a burst is fixed by the design. Neither should ever be modified by a line of code, and const says so in a way that holds.
Note the combination with Chapter 3.4: const std::uint32_t says exactly 32 bits, unsigned, and it will not change. Three facts, enforced, in one declaration. That is the kind of density a type system buys you.
4. A const Object Must Be Initialized
This follows from the promise, and it connects directly to Chapter 3.8.
int main()
{
const int setup_cycles; // INCORRECT: no initialiser
return setup_cycles;
}constnoinit.cpp:3:15: error: default initialization of an object
of const type 'const int'Work out why that has to be an error.
Chapter 3.8 §1 established that int x; inside a function writes nothing — the object holds an indeterminate value. Normally you can recover by assigning later. For a const object you cannot: assignment is exactly what const forbids.
So an uninitialized const object would be permanently stuck holding an indeterminate value, and reading it would be undefined behaviour with no way to fix it. The language refuses to create that situation.
This is a small, satisfying example of rules interlocking rather than being arbitrary. Two independent facts — default initialization writes nothing, and const forbids assignment — combine to make a third rule necessary.
5. What const Does Not Mean
Three clarifications, each a real misconception.
It does not mean "compile-time constant". A const object's value can be computed when the program runs:
const int total_cycles = setup_cycles + transfers * cycles_per_transfer;That is a perfectly good const. The value is fixed once it is set — not necessarily known while compiling. C++ has a separate keyword, constexpr, for values that must be known at compile time, and Chapter 21.2 teaches it. The two are related and are not the same thing.
It does not mean the storage is read-only hardware. const is a rule about what your program may do, checked by the compiler. It is not a statement about memory protection.
It does not make a value safe from every kind of change. That sounds like a strange caveat now, and it becomes meaningful from Module 8, where you will meet objects reachable through more than one name. For objects you declare and use directly — this whole module — const means what it looks like it means.
6. Where const Shows Up Later
This chapter covers const on objects. The qualifier appears in several other places, each of which is a chapter of its own, and it is worth knowing they exist so the word is not a surprise:
| Form | What it qualifies | Taught in |
|---|---|---|
const int x = 3; | The object itself | This chapter |
const int& x | A reference that may not modify what it refers to | 6.5, 8.7 |
const int* p / int* const p | What a pointer may modify, or whether it may be repointed | 8.7 |
int value() const | A member function that does not modify its object | 11.7 |
Each of those is the same underlying idea — a promise the compiler enforces — applied to something more complicated than a plain object. Getting the simple case into your hands now is what makes the others readable later.
7. Mistakes Worth Making Once
Using a comment instead of const. The comment is not checked and goes stale. const costs one word.
Leaving a const object uninitialized. It will not compile, and now you know why it cannot: there would be no legal way to ever give it a value.
Thinking const means compile-time constant. A const can be computed at run time. constexpr is the one that must be known while compiling — Chapter 21.2.
Declaring everything non-const by default. The reader then cannot tell which objects are settled and which vary, and the information is free to provide.
Adding const to a value you then need to change. That is the compiler doing its job, not an obstacle. It is asking whether the object should vary — and the answer is sometimes yes, in which case remove it deliberately.
Expecting const to mean read-only memory. It is a compile-time rule about your program, not a statement about hardware protection.
8. What You Should Be Able to Say Now
constqualifies an object with a promise: its value will not be modified after initialization.- The object's type is unchanged —
const intis still anint, with a constraint attached. - Unlike a comment, the promise is checked by the compiler on every line that touches the object. Breaking it is an error, not a warning.
- Measured: assigning to a
const intproduced "cannot assign to variable … with const-qualified type". - A
constobject must be initialized on its declaring line. - That rule is forced by two others: default initialization writes nothing, and
constforbids later assignment — so an uninitializedconstcould never be given a value. constcombines with everything else a declaration says:const std::uint32_tis exactly 32 bits, unsigned, and fixed.- If an object does not need to change, make it
const. It documents what is settled and enforces the initialization habit from Chapter 3.7. constdoes not mean compile-time constant —constexpris that, in Chapter 21.2.constdoes not mean read-only storage; it is a rule about what your program may do.- The same qualifier appears on references, pointers and member functions, each with a later chapter.
9. Exercises
Exercise 1 — compile or not? For each, say whether it compiles and why: (a) const int a = 3; (b) const int b; (c) const int c = 3; c = 4; (d) const int d = setup_cycles + 1; where setup_cycles is a const int.
Exercise 2 — derive the rule. Without looking at §4, explain why C++ must reject an uninitialized const object, using the two facts it follows from.
Exercise 3 — comment versus const. A header contains int max_outstanding = 16; // never modify. Give two specific ways that line can become false without anyone noticing, and the one-word change that prevents both.
Exercise 4 — which should be const? In a function with these locals, say which should be const and why: a loop counter; a peripheral's base address; a running error total; the number of transfers in a burst, read once from a configuration.
Exercise 5 — correct the claim. A colleague says "const means the value is known at compile time, so the compiler can substitute it everywhere." Identify what is wrong, and name the keyword that does mean that.
Exercise 6 — the deliberate removal. You mark an object const and the build then fails on a line that assigns to it. Describe the two legitimate responses, and say what question the compiler has actually asked you.
Exercise 7 — read the density. Explain, in one sentence each, the three separate facts stated by const std::uint32_t register_base = 0x4000'0000u;.
10. Summary
constis a promise that an object will not be modified, attached to the declaration.- The difference from a comment is enforcement. A comment is never checked and goes stale;
constfails the build. - Measured: assigning to a
const intis a compile error, not a warning. - A
constobject must be initialized — forced by default initialization writing nothing andconstforbidding assignment later. - It combines with the rest of the declaration:
const std::uint32_tsays width, signedness and immutability at once. - Default to
constfor anything that does not need to change. It marks what is settled and enforces the initialization habit. constis notconstexpr— aconstvalue may be computed at run time.constis a rule about your program, not about read-only memory.- The same qualifier returns for references, pointers and member functions, each with its own chapter.
One chapter remains, and it is about the opposite kind of economy. const adds a word to a declaration to say more; the last feature in this module removes a word and asks the compiler to work something out instead. That sounds like it should make C++ behave like a language where types are decided while the program runs, and it is important that you do not read it that way — because it is the exact opposite. Chapter 3.10 is auto.
Standards & specifications
- Governing standard
- ISO/IEC 14882 (the C++ language standard)(opens ISO/IEC (JTC 1/SC 22/WG 21) in a new tab)
Defines the C++ language and its standard library — the type system and templates, the object model and object lifetime, initialisation and overload resolution, the memory model and the containers, algorithms and utilities the library provides. Like C's standard it is a FAMILY of editions (C++98/03, C++11, C++14, C++17, C++20, C++23) and the editions are NOT interchangeable: a feature this curriculum relies on may be unavailable, differently specified or merely proposed in another edition, so each lesson names the edition its claim depends on. It does not define any foreign-function interface to a hardware description language, nor what a compiler actually emits, nor platform behaviour on real silicon — those are the implementation's and the device's contracts. Working drafts published by WG21 are freely available and are what most engineers read day to day; a draft is not the published standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the C++ Programming curriculum.
