Behavior of const auto pointers in C++

Viewed 3804

This answer claims that a const auto pointer behaves the same as a const 'regular' (i.e., non-auto) pointer, which is what I would expect.

However, the following code compiles and outputs 100:

int n{ 99 };
const auto nPtr = &n;
++(*nPtr);
std::cout << n << '\n';

To dig a little deeper, I checked the types of all 4 kinds of pointers and this is the result I got:

Code

int n{ 99 };

int* intPtr = &n;
const int* intConstPtr = &n;

auto autoPtr = &n;
const auto autoConstPtr = &n;

std::cout << "intPtr: " << typeid(intPtr).name() << '\n';
std::cout << "intConstPtr: " << typeid(intConstPtr).name() << '\n';

std::cout << "autoPtr: " << typeid(autoPtr).name() << '\n';
std::cout << "autoConstPtr: " << typeid(autoConstPtr).name() << '\n';

Output

intPtr: int * __ptr64

intConstPtr: int const * __ptr64

autoPtr: int * __ptr64

autoConstPtr: int * __ptr64

So the compiler seems to be completely ignoring the const keyword with the auto pointer. Does anyone know why this is?

2 Answers

When you write const auto, you are saying: make the type of deduced variable, const. The type of the deduced variable is int *, that, is, pointer-to-int. So you are saying: a const variable, of type pointer-to-int. Or, more formally: int * const. The type of the pointee is still just int, non-const-qualified, so modifying is no problem. You just can't change what the pointer is pointing to. If you want to control the const-ness of the pointed to type, you can't just use auto because there's no awareness that it is specifically deducing to a pointer type. So you would have to write:

const auto * intConstPtr = &n;

The auto here is just deducing to the pointee (int), which is what gets qualified by the const. So this deduces to: pointer-to-const-int. You could also write:

const auto * const intConstPtr = &n;

For type const-pointer-to-const-int. Though, at that point, you should probably just use a reference. This is why const pointers (as opposed to pointers-to-const) aren't all that common in C++, at least in some codebases (there are certainly exceptions).

Here, const auto is being converted to int *const, not const int*. The difference is that it’s a constant pointer to a (variable) int, not a (variable) pointer to a constant int. In this case, that means you can do ++(*nPtr);, as you do, but you cannot change nPtr to point to a different int.

To see this, try adding the lines

int i{ 17 };
nPtr = &i

The four variants of int pointers with different const qualification, specified without auto, are:

  • int*: A modifiable pointer to a modifiable int. You can change which int it points to, and you can use it to change the value of that int. This is what you get with just auto nPtr = &n.
  • int *const: A fixed pointer to a modifiable int. It will always point to the same int, but you can use it to change the value of that int. This is what you get with const auto nPtr = &n or auto const nPtr = &n.
  • int const * or const int*: A modifiable pointer to a constant int. You can change which int it points to, but you cannot use it to change the value of that int.
  • int const *const or const int *const: A constant pointer to a constant int. You cannot change which int it points to, and you cannot use it to change the value of that int.
Related