c++ - reinterpret_cast - ¿hay alguna diferencia entre la conversión estática a rvalue reference y std:: move
static_cast c++ definition (3)
Puede usar static_cast<A &&>(a)
cuando a es un valor, pero no debe usar std::move(a)
.
Cuando usa A && a = std::move(A())
, obtiene una referencia pendiente.
La idea básica es que la vida útil de un temporal no se puede extender aún más "pasándolo": una segunda referencia, inicializada a partir de la referencia a la cual se vinculó el temporal, no afecta su vida útil.
La implementación de std::move
es algo así como
template <typename T>
constexpr decltype(auto) move(T && __t) noexcept // when used in std::move(A()),
// the lifetime of the temporary object is extended by __t
{
return static_cast<typename std::remove_reference<T>::type &&>(__t); // a xvalue returned, no lifetime extension
}
auto && a = std::move(A()); // the anonymous object wiil be destructed right after this line
La descripción para el reparto estático dice
Si new_type es un tipo de referencia rvalue, static_cast convierte el valor de expresión a xvalue. Este tipo de static_cast se usa para implementar la semántica de movimiento en std :: move. (Desde C ++ 11)
¿Esto confirma que los siguientes son equivalentes?
(UNA)
X x1;
X x2 = static_cast<X&&>(x1);
(SEGUNDO)
X x1;
X x2 = std::move(x1);
Sí, hay una diferencia muy importante: std::move
documentos lo que quieres hacer. Además, el reparto es propenso a escribir errores como un tipo X
olvidado o incorrecto.
Como se puede ver, std::move
es aún menos que escribir.
T && En C ++ 11 es una referencia de valor. Se comportan como referencia de valor de C ++ 98,03. Su objetivo - ser un candidato para mudarse. En C ++ 98, tal construcción puede aparecer en refrie colapsando
std :: move - convierte la expresión en rvalue. Podría llamarse rvalue_cast , pero dicha palabra clave no existe.
Fundido explícito al tipo T && posible en principio. El estándar real cuesta algo de dinero, pero en el borrador de la norma ISO / IEC 14882: 2011 existe tal información
5.2.9 Reparto estático
8)
Las conversiones lvalue-to-rvalue (4.1), array-to-pointer (4.2) y function-to-pointer (4.3) se aplican al operando ...
Desde el punto de vista práctico, es más conveniente usar std :: move. Imagina tal ejemplo:
#include <stdio.h>
#include <utility>
class A
{
public:
A () {printf ("A ()" "/n");}
A (const A &) {printf ("A (&)" "/n");}
A (A &&) {printf ("A (&&)" "/n");}
A (const A &&) {printf ("A (const &&)" "/n");}
~ A () {printf ("~ A ()" "/n");}
};
int main ()
{
const A obj;
A obj2 (std::move (obj)); // 1-st approach
A obj3 (static_cast <const A&&> (obj)); // 2-nd approach
}
En cuanto a mí, el primer enfoque es
- más conveniente (¿debería realizar static_cast para const A && , o para A && ?)
- más explícitamente (puedo usar la búsqueda en el editor de texto para encontrar std :: move in project)
- menos propenso a errores cuando el desarrollador de software escribe código