Vi esto aquí: Move Constructor llamando a clase base Move Constructor
Podría alguien explicar:
- la diferencia entre
std::moveystd::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

movecuando quieres mover un valor yforwardcuando quieres usar el reenvío perfecto. Esto no es ciencia espacial aquí;)Respuestas:
std::movetoma 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::forwardtiene 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_castdirectamente y escribir una buena explicación de lo que está haciendo.fuente
std::forwardel ú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::forwardystd::moveno son más que moldes.Lo anterior
xconvierte la expresión lvalue de tipo X en una expresión rvalue de tipo X (un valor x para ser exactos).moveTambié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::forwardusted puede seleccionar el destino hasta cierto punto:Convierte la expresión lvalue
xde 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).
forwardpuede 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::forwardse 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::moveofrece 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 sixno es un valor por sí mismo.fuente