Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a const pointer to a const data member and the 'auto' keyword. A bit confused

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

like image 620
Pete Avatar asked May 14 '15 00:05

Pete


People also ask

Can a const function return a pointer?

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.

What does it mean to return a const?

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.

Which is the correct way to declare a pointer to constant object?

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'.

What happens if you try to change a const?

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 .


2 Answers

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

like image 109
Praetorian Avatar answered Oct 18 '22 10:10

Praetorian


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.

like image 45
StenSoft Avatar answered Oct 18 '22 10:10

StenSoft