Skip to content
VLSI Mentor

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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    int       cycle_count  = 19;    // may change
    const int setup_cycles = 3;     // will not change

Both 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    int setup_cycles = 3;    // do not modify this

That line and the const line communicate the same thing to a human reader. Here is what separates them:

A commentconst
Read byPeople, if they lookThe compiler, always
CheckedNeverOn every line that touches the object
When it is wrongNobody finds outThe build fails
After six months of editsPossibly a lieStill 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:

Azvya Education Pvt. Ltd.VLSI Mentor
constbad.cpp — INCORRECT. Does not compile.
int main()
{
    const int setup_cycles = 3;
    setup_cycles = 4;            // INCORRECT
    return setup_cycles;
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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.

const turns a statement of intent into a constraint the compiler checks. That is the whole feature.

3. A Working Example

Azvya Education Pvt. Ltd.VLSI Mentor
constdemo.cpp — complete program
#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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
register_base = 1073741824
setup_cycles  = 3

Both 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.

Azvya Education Pvt. Ltd.VLSI Mentor
constnoinit.cpp — INCORRECT. Does not compile.
int main()
{
    const int setup_cycles;      // INCORRECT: no initialiser
    return setup_cycles;
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    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:

FormWhat it qualifiesTaught in
const int x = 3;The object itselfThis chapter
const int& xA reference that may not modify what it refers to6.5, 8.7
const int* p / int* const pWhat a pointer may modify, or whether it may be repointed8.7
int value() constA member function that does not modify its object11.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

  1. const qualifies an object with a promise: its value will not be modified after initialization.
  2. The object's type is unchanged — const int is still an int, with a constraint attached.
  3. 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.
  4. Measured: assigning to a const int produced "cannot assign to variable … with const-qualified type".
  5. A const object must be initialized on its declaring line.
  6. That rule is forced by two others: default initialization writes nothing, and const forbids later assignment — so an uninitialized const could never be given a value.
  7. const combines with everything else a declaration says: const std::uint32_t is exactly 32 bits, unsigned, and fixed.
  8. 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.
  9. const does not mean compile-time constant — constexpr is that, in Chapter 21.2.
  10. const does not mean read-only storage; it is a rule about what your program may do.
  11. 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

  • const is 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; const fails the build.
  • Measured: assigning to a const int is a compile error, not a warning.
  • A const object must be initialized — forced by default initialization writing nothing and const forbidding assignment later.
  • It combines with the rest of the declaration: const std::uint32_t says width, signedness and immutability at once.
  • Default to const for anything that does not need to change. It marks what is settled and enforces the initialization habit.
  • const is not constexpr — a const value may be computed at run time.
  • const is 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.