Update: The code is ill-formed in C++11. Answer below is for C++14. See note at the end of this answer.
I believe this code is both well-formed and well-defined. Here's why.
The result of std::move
is an xvalue [1], which is a type of glvalue; and converting a glvalue to an lvalue reference with reinterpret_cast
appears to be allowed by the wording of the standard:
A glvalue expression of type T1
can be cast to the type “reference to T2
” if an expression of type “pointer
to T1
” can be explicitly converted to the type “pointer to T2
” using a reinterpret_cast
. The result refers
to the same object as the source glvalue, but with the specified type. [ Note: That is, for lvalues, a reference
cast reinterpret_cast<T&>(x)
has the same effect as the conversion *reinterpret_cast<T*>(&x)
with
the built-in &
and *
operators (and similarly for reinterpret_cast<T&&>(x)
). — end note ] No temporary
is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called.73
Since "pointer to int
" can be converted to "pointer to int
", this reinterpret_cast
is also allowed. The standard doesn't say anything about whether the destination type has to be an lvalue reference or rvalue reference.
The result of the cast is well-defined by the paragraph above: it refers to the same object as the source glvalue---that is, a temporary int
object with the value 5
. ([dcl.init.ref] specifies that a temporary is created when a prvalue is bound to a reference.)
Accessing the value through the int&
also doesn't violate any aliasing rules since the original object was also of type int
. In fact I believe it would even be well-defined to modify the temporary through the lvalue thus obtained.
Note: The C++11 wording says "lvalue expression", not "glvalue expression". The wording with "glvalue expression" is from N3936, which is the final working draft for C++14. I'm not an expert in how the standardization process works, but I believe this means that the change of "lvalue" to "glvalue" was already voted in by the committee, and when ISO publishes the C++14 standard, it's going to be pretty similar to what it says above.
[1] Except in the rare case in which the argument is a function; in that case the result is an lvalue, since there are no function rvalues.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…