While studying constants, pointers and references, I encountered the following problem. The following code throws an error: cannot bind non-const lvalue reference of type ‘const int*&’ to an rvalue of type ‘const int*’
.
int* numPtr = new int(5);
const int*& numPtrRef = numPtr;
But the following 2 blocks of code work without errors.
int* numPtr = new int(5);
const int* const& numPtrRef = numPtr;
const int* numPtr = new int(5);
const int*& numPtrRef = numPtr;
I don't understand why this is happening. It seems like non-const objects can be assigned to const objects, but for some reason the error seems to say the opposite. Please help me figure this out.
I do not have any practical goal, I want to understand the c language, so I'm wondering why this code gives an error.
CodePudding user response:
If first example worked then it could lead to mind-boggling bugs:
int * numPtr{};
const int * & numPtrRef = numPtr; // assume this is working
const int x{42};
numPtrRef = &x;
// now numPtr also points to const x
*numPtr = 24; // OOPS!
Therefore language does not permit binding a reference to object of type "mutable pointer to immutable object" to an object of type "mutable pointer to mutable object".
No such problems happen in case of examples 2 and 3.
CodePudding user response:
Why (3) works should be obvious.
(2) works because numPtrRef
, being a reference to const
(to const pointer to const int), can bind to temporaries. When you initialize it with int *
(which is not the type it wants, const int *
), a temporary pointer with the right type is created from the original pointer, and the reference is initialized to point to the temporary (whose lifetime is then extended to match the lifetime of the reference).
(1) doesn't work, because references to non-const types can't bind to temporaries.
It can be made to work by casting the original pointer to a reference to the correct type:
const int *& numPtrRef = const_cast<const int *&>(numPtr);
const_cast
essentially acts as reinterpret_cast
here, with a little more protection.
Normally this would be a strict aliasing violation, but there's an exception to this rule (1, 2) permitting a mismatch in const
ness.