Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I right in saying that const_cast followed by modification on a ref-to-const bound to a temporary is okay?

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!)

like image 773
Lightness Races in Orbit Avatar asked Nov 23 '11 15:11

Lightness Races in Orbit


People also ask

Can you modify a const reference C++?

But const (int&) is a reference int& that is const , meaning that the reference itself cannot be modified.

Why is const correctness important?

The benefit of const correctness is that it prevents you from inadvertently modifying something you didn't expect would be modified.

Can a const reference call a non const function?

Once you have a const object, it cannot be assigned to a non-const reference or use functions that are known to be capable of changing the state of the object.

Is const cast Safe?

const_cast is safe only if you're casting a variable that was originally non- const . For example, if you have a function that takes a parameter of a const char * , and you pass in a modifiable char * , it's safe to const_cast that parameter back to a char * and modify it.


1 Answers

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.

like image 130
James Kanze Avatar answered Sep 21 '22 18:09

James Kanze