Skip to content

32 Intermediate The Hundred

The const Object That Changed

a const object, a const method, and something still moves

struct Buffer {
    int* data;
    int size;

    void wipe() const {
        for (int i = 0; i < size; ++i)
            data[i] = 0;
    }
};

int main() {
    int storage[4] = {7, 8, 9, 10};
    const Buffer b{storage, 4};

    std::cout << "before:";
    for (int v : storage)
        std::cout << ' ' << v;

    b.wipe();   // b is const... so nothing can change, right?

    std::cout << "\nafter: ";
    for (int v : storage)
        std::cout << ' ' << v;
    std::cout << '\n';
}

Compile it. Does wipe() const even build — and if it runs, what does it print?

Answer

It builds without a single warning: before: 7 8 9 10, then after: 0 0 0 0. The const object just zeroed the array.

Why

Inside a const member function this is const Buffer*, so every member picks up the qualifier — data becomes int* const (entry 31), a pointer you may not repoint. It says nothing about the ints at the far end: const was never part of their type, so data[i] is a plain int&, and assigning to it is well-defined. That is what "const is shallow" means — the qualifier sticks to the pointer and refuses to follow the arrow. b itself is unchanged byte for byte; the array it points at was never const. Swap the body for data = nullptr; and GCC stops you at once — "assignment of member ‘Buffer::data’ in read-only object" — while -Wall -Wextra stays silent on the code above.

The fix

Put the const where the data is, or stop holding the data through a raw pointer:

const int* data;         // pointee is const too → "error: assignment of read-only location"
std::vector<int> data;   // by value: const reaches the elements, same error

Then hand out const int* from const accessors and int* only from non-const ones; for a pointer you must keep, GCC's std::experimental::propagate_const pushes const through it.

Takeaway: const stops at the pointer — it does not follow the arrow.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry