I've recently been learning C++ and just today have been introduced to const and the concept of const correctness. In an attempt to better understand the theory, I've been writing a series of simple programs to make sure that I understand the concept correctly. I thought I understood everything, but then when using the auto keyword in one of the programs, I seem to have got a bit stuck.
In order to test that I understood how const pointers work I wrote a simple program. I won't bother posting the whole thing since there's only two parts of it that are relevant. I have a class with a const data member of type int:
const int tryToChangeMe;
Within this class I also have a member function that returns a const pointer to the above const int:
const int* const MyClass::test()
{
return &tryToChangeMe;
}
In my main function I then call the above function, making use of the auto keyword. In order to test that what I think I know about const is correct I then attempt to reassign the tryToChangeMe variable through the pointer. Like so:
auto temp = myClass.test();
*temp = 100;
As I expected, the program wouldn't compile due to the error that I caused when trying to assign a value to a const variable. However, I didn't just return a pointer to const, I returned a const pointer to a const (at least that's what I thought I did). So to test this, I attempted to reassign the pointer to a new memory address, quite confident that I'd get a similar compilation error:
temp = new int;
But quite confusingly the program compiled without any issue. Stepping through with the debugger revealed that sure enough, the pointer was losing its original address and being assigned a brand new one. Wondering what was going on, I just happened by chance to remove the auto keyword and replace it with the variable's full type:
const int* const temp = myClass.test();
Upon testing everything again, the results were as expected and this time I was not able to reassign the pointer to a new address.
So after all that I guess my question is, why? Why does the auto keyword allow you to bypass the const qualifier of pointers? Did I do something wrong?
By the way, I'm not sure if it matters but I'm using Visual Studio 2015 preview
So does it make sense to return a const pointer? It depends on what is const . If the constness refers to the pointed object, yes it does. If you try to make the pointer itself const, it doesn't make sense as it will be ignored.
If you say that a function's return value is const: const int g(); you are promising that the original variable (inside the function frame) will not be modified. And again, because you're returning it by value, it's copied so the original value could never be modified via the return value.
We declare a pointer to constant. First, we assign the address of variable 'a' to the pointer 'ptr'. Then, we assign the address of variable 'b' to the pointer 'ptr'. Lastly, we try to print the value of 'ptr'.
Whenever we use const qualifier with variable name, it becomes a read-only variable and get stored in . rodata segment. Any attempt to modify this read-only variable will then result in a compilation error: “assignment of read-only variable”. The variables declared using const keyword, get stored in .
As already mentioned, auto
ignores top level cv-qualifiers. Read this article to learn the details of how auto
and decltype
work.
Now, even if auto
didn't ignore the const
, in your case, temp
would still not be const
because top level cv-qualifiers on return types are ignored if the type being returned is of non-class type.
g++ even produces the following warning with -Wextra
warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
This can be demonstrated by using C++14's decltype(auto)
. Unlike auto
, decltype(auto)
doesn't discard references and top level cv-qualifiers. If you modify your example by adding the following lines the code will still compile, proving that temp
is not a const
pointer.
decltype(auto) temp = myClass.test();
static_assert(std::is_same<const int*, decltype(temp)>{}, "");
On the other hand, if test()
returns an object of class type with a top level cv-qualifier, then auto
would still discard const
, but decltype(auto)
wouldn't.
Live demo
The reason is that auto
variables are not by default const
. The fact that you return const
value does not mean it has to be assigned to a const
variable; the value is copied after all (eventhough the value is a pointer). You can try it easily with explicit type specification as well. The value stored in myClass
won't be changed when changing the variable temp
and the pointer target is still const
so constness is still honored.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With