Question

I would like to check my understanding and conclusions on this matter.


On IRC, it was asked:

Is it acceptable to const_cast a const reference that's bound to a temporary object?

Translating: he has a ref-to-const bound to a temporary, and he wants to cast away its const-ness to modify it.

My response was that I'd asked a similar question previously, where the consensus seemed to be that temporaries themselves are not inherently const, and thus that you can cast off the const-ness of a reference you have to them, and modify them through the result. And, as long as that original ref-to-const still exists, this won't affect the temporary's lifetime.

That is:

int main()
{
   const int& x = int(3);

   int& y = const_cast<int&>(x);
   y = 4;

   cout << x;
}
// Output: 4
// ^ Legal and safe

Am I right?


(Of course, whether or not such code is actually advisable is another matter entirely!)

Was it helpful?

Solution

No.

First, as far as I can tell, whether it is a literal or not is irrelevant. Rvalues of non-class types always have non-cv qualified types (§3.10/9), however, in §8.5.3 (initialization of a reference), we have:

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

[...]

--

Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy initialization (8.5). The reference is then bound to the temporary. If T1 is reference-related to T2, cv1 must be the same cv-qualification as, or greater cvqualification than, cv2; otherwise, the program is ill-formed.

(All of the preceding points concern either lvalues or class types.)

In our case, we have:

int const& x = ...;

So cv1 T1 is int const, and the temporary object we create has type int const. This is a top level const (on the object), so any attempt to modify it is undefined behavior.

At least, that's my interpretation. I wish the standard were a bit clearer about this.

OTHER TIPS

The answer depends on how the temporary is created and how the reference is initialized.

If you explicitly created the temporary yourself as an object of non-const type and the situation guarantees that the const-reference is attached specifically to the temporary you created, then you can safely cast away the constness of the reference and modify the object.

On the other hand, if the temporary was implicitly created for you by the compiler, then the temporary itself will be const. In that case modifying that temporary leads to UB.

Unfortunately, the C++ language standard by itself does not seem to seem to guarantee any situations where the first initialization approach is necessarily taken. In any context the compiler is allowed to introduce an extra temporary copy of your original temporary. The new temporary will be const (as stated above) and therefore non-modifiable. Whether this happens or not is implementation-defined, as stated in 8.5.3/5.

So, in general case the answer is no, while an implementation-specific answer might be different.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top