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