C++ const Correctness

Const correctness means using const anywhere a value should not be changed. It helps the compiler protect your intent and makes functions and classes easier to trust.

In modern C++, const is not just for constants like numbers. It is also used with references, function parameters, return values, and class methods.

Why const Correctness Matters

Programs get easier to understand when code clearly says what it will and will not modify. If a function receives a const reference, readers know the function can inspect the object but should not change it. If a member function is marked const, it promises not to change the object it is called on.

The compiler checks these promises. If you accidentally try to modify a const value, C++ reports an error at compile time instead of letting the bug run.

Common Uses Of const

Use Meaning
const int limit = 10; limit cannot be assigned a new value.
void show(const Book& book) The function can read book without copying it, but cannot modify it.
int pages(void) const The method can be called on a const object and cannot change normal data members.

Example: const References And const Methods

This example uses const in several places. The value maxRetries is fixed, readOnlyScore is a reference used only for reading, and printBook() accepts a book without making a copy or changing it.

#include <iostream>
#include <string>

class Book {
private:
    std::string title;
    int pages;

public:
    Book(std::string bookTitle, int pageCount) {
        title = bookTitle;
        pages = pageCount;
    }

    const std::string& getTitle(void) const {
        return title;
    }

    int pageCount(void) const {
        return pages;
    }

    void rename(std::string newTitle) {
        title = newTitle;
    }
};

void printBook(const Book& book) {
    std::cout << book.getTitle() << " has "
              << book.pageCount() << " pages" << std::endl;
}

int main(void) {
    const int maxRetries = 3;
    int score = 10;
    const int& readOnlyScore = score;

    std::cout << "Max retries: " << maxRetries << std::endl;
    std::cout << "Score through const reference: "
              << readOnlyScore << std::endl;

    const Book archived("Modern C++", 180);
    printBook(archived);

    Book guide("Draft Title", 210);
    guide.rename("Const Correctness");
    printBook(guide);

    return 0;
}

Output:

Max retries: 3
Score through const reference: 10
Modern C++ has 180 pages
Const Correctness has 210 pages

How The Example Works

maxRetries is declared with const, so it must be initialized when it is created and cannot later be assigned a different value. This is useful for named values that should stay fixed.

readOnlyScore is a const int&. It refers to score, but code using that reference cannot modify the integer through the reference. Const references are common function parameters because they avoid copying large objects while still preventing accidental changes.

printBook() takes const Book&, so it can accept both Book and const Book objects. Inside that function, only const member functions can be called on book.

const Member Functions

The methods getTitle() and pageCount() end with const. That final const means the method promises not to change the object’s normal data members. Because of that promise, these methods can be called on archived, which is a const Book.

The method rename() is not marked const because it changes the title. That means it can be called on guide, but not on archived.

Good Habits

  • Use const for values that should not change after initialization.
  • Pass large read-only objects as const T& to avoid copying.
  • Mark member functions const when they only inspect the object.
  • Let compiler errors guide you when a function needs to be more const-correct.

Takeaway: const correctness lets C++ enforce read-only promises, making your functions and classes safer to use.