const T* and T* const
A pointer is a slip with a house's address. Two different things can be forbidden on such a slip:
- changing anything in the house: you may come and look, but not touch;
- rewriting the slip itself: the address is written for good, though things in the house may change.
In C++, both bans are written with the same word, const. The variable a in this program is declared without const, yet the compiler does not let the pointer p change it:
int main() {
int a = 1;
int b = 2;
const int* p = &a;
*p = 5; // ✗
p = &b;
return *p;
}error: read-only variable is not assignableThe error is only on the line *p = 5;, while the line p = &b; compiles. What const forbids in a pointer declaration depends on where the const itself stands.
Pointer to const
const int* p is a pointer to const. It is a slip marked "look only":
- the value can be read through
pbut not changed; pmay also point to a variable withoutconst: the ban covers only writing throughp, anda = 5;still works;pitself is an ordinary variable, so it can be pointed elsewhere, as in the linep = &b;.
A function that only reads numbers through a pointer declares its parameter as const int* data. This way it promises not to change the caller's numbers: an accidental write such as data[0] = 0; in the body fails with the same error as *p = 5;.
Const pointer
When const comes after the *, the pointer itself becomes constant. int* const q is a const pointer. It is a slip with the address written for good:
qcannot be pointed elsewhere, so it is initialized right away;- the value can be changed through
q.
const int* const r forbids both.
#include <iostream>
int main() {
int a = 1;
int b = 2;
const int* p = &a;
p = &b;
int* const q = &a;
*q = 5;
std::cout << *p << ' ' << a << '\n'; // 2 5
}Let's go through the example line by line:
const int* p = &a;is a "look only" slip with the address ofa.p = &b;rewrites it: nowppoints tob.int* const q = &a;is a slip with the address ofawritten for good.*q = 5;changesathroughq, which is allowed.- The program prints
2 5:*preadsb, andanow holds5.
Where const stands
What decides is where const stands relative to the *. To the left of the asterisk it applies to the value, and to the right it applies to the pointer itself. That is why int const* p means the same as const int* p.
A declaration is easiest to read from right to left, starting at the name:
int* const qreads "qis a const pointer toint";const int* preads "pis a pointer to aconst int".
Common mistake
The address of a const variable is stored in a plain pointer:
int main() {
const int limit = 10;
int* p = &limit; // ✗
return *p;
}error: cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'Through an int*, the value of limit could be changed, so the compiler rejects this initialization. Declare the pointer as const int* p = &limit;.
Key points
const int* pforbids changing the value throughp, butpcan be pointed elsewhere.int* const qforbids pointingqelsewhere, but the value can be changed through it.constto the left of*applies to the value, to the right of it to the pointer itself.- A
const int* dataparameter promises that the function only reads the numbers.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.