Vi esto aquí: Move Constructor llamando a clase base Move Constructor
Podría alguien explicar:
- la diferencia entre
std::move
ystd::forward
, preferiblemente con algunos ejemplos de código? - Cómo pensarlo fácilmente y cuándo usar qué
c++
c++11
perfect-forwarding
aCuria
fuente
fuente
move
cuando quieres mover un valor yforward
cuando quieres usar el reenvío perfecto. Esto no es ciencia espacial aquí;)Respuestas:
std::move
toma un objeto y le permite tratarlo como temporal (un valor r). Aunque no es un requisito semántico, normalmente una función que acepta una referencia a un valor r lo invalidará. Cuando veastd::move
, indica que el valor del objeto no debe usarse después, pero aún puede asignar un nuevo valor y continuar usándolo.std::forward
tiene un solo caso de uso: para convertir un parámetro de función con plantilla (dentro de la función) a la categoría de valor (lvalue o rvalue) que la persona que llama usó para pasarlo. Esto permite que los argumentos de valor se transmitan como valores, y los valores se transmitan como valores, un esquema llamado "reenvío perfecto".Para ilustrar :
Como Howard menciona, también hay similitudes ya que ambas funciones simplemente se convierten al tipo de referencia. Pero fuera de estos casos de uso específicos (que cubren el 99.9% de la utilidad de los moldes de referencia de valor), debe usar
static_cast
directamente y escribir una buena explicación de lo que está haciendo.fuente
std::forward
el único caso de uso sea el reenvío perfecto de argumentos de función. Me he encontrado con situaciones en las que quiero reenviar perfectamente otras cosas, como miembros del objeto.Ambos
std::forward
ystd::move
no son más que moldes.Lo anterior
x
convierte la expresión lvalue de tipo X en una expresión rvalue de tipo X (un valor x para ser exactos).move
También puede aceptar un valor r:y en este caso es una función de identidad: toma un valor de tipo X y devuelve un valor de tipo X.
Con
std::forward
usted puede seleccionar el destino hasta cierto punto:Convierte la expresión lvalue
x
de tipo X en una expresión de tipo Y. Existen restricciones sobre lo que Y puede ser.Y puede ser una Base de X accesible, o una referencia a una Base de X. Y puede ser X, o una referencia a X. No se pueden descartar los calificadores cv
forward
, pero se pueden agregar calificadores cv. Y no puede ser un tipo que sea simplemente convertible de X, excepto a través de una conversión de Base accesible.Si Y es una referencia de valor, el resultado será una expresión de valor. Si Y no es una referencia de lvalue, el resultado será una expresión de rvalue (xvalue para ser precisos).
forward
puede tomar un argumento rvalue solo si Y no es una referencia lvalue. Es decir, no puede emitir un valor r a lvalue. Esto se debe a razones de seguridad, ya que esto generalmente lleva a referencias colgantes. Pero emitir un rvalue a rvalue está bien y está permitido.Si intenta especificar Y a algo que no está permitido, el error se detectará en tiempo de compilación, no en tiempo de ejecución.
fuente
std::forward
, luego de ejecutar esa función, ¿puedo usar ese objeto? Soy consciente de que, en caso destd::move
, es un comportamiento indefinido.move
: stackoverflow.com/a/7028318/576911 Paraforward
, si pasa un valor, su API debería reaccionar como si recibiera un valor. Normalmente esto significa que el valor no se modificará. Pero si es un valor no constante, su API puede haberlo modificado. Si pasa un valor r, esto normalmente significa que su API puede haberse movido de él y, por lo tanto, se aplicaría stackoverflow.com/a/7028318/576911 .std::forward
se usa para reenviar un parámetro exactamente de la forma en que se pasó a una función. Justo como se muestra aquí:¿Cuándo usar std :: forward para reenviar argumentos?
El uso
std::move
ofrece un objeto como un valor r, para posiblemente hacer coincidir un constructor de movimiento o una función que acepte valores. Lo hacestd::move(x)
incluso six
no es un valor por sí mismo.fuente