问题
I would like to check my understanding and conclusions on this matter.
On IRC, it was asked:
Is it acceptable to
const_cast
aconst
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!)
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/8245027/am-i-right-in-saying-that-const-cast-followed-by-modification-on-a-ref-to-const