std::move y std::forward
Convierta lvalues en rvalues con std::move y conserve la categoría de valor con std::forward.
std::move y std::forward es una lección gratuita de C++ Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C++ Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C++ Academy incluye 4 lecciones en total.
Dos parientes, funciones diferentes
std::move y std::forward son conversiones que se realizan en tiempo de compilación. Se parecen, pero resuelven problemas diferentes.
std::move: siempre convierte a rvalue
std::move(x) convierte incondicionalmente x en una referencia rvalue. La función receptora puede entonces apropiarse de sus recursos.
std::string s = "Hello";
std::string t = std::move(s); // move-constructs t from s
// s is now in a valid-but-unspecified stateCuándo usar move
Use std::move en:
- Constructores de movimiento y operadores de asignación por movimiento
- Al devolver una variable local cuando quiera forzar un movimiento (rara vez es necesario, ya que normalmente se aplica RVO)
- Al pasar una variable local que ya no necesita a una función sumidero
Implementación de std::move
Es simplemente un static_cast disfrazado:
template <typename T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept {
return static_cast<typename std::remove_reference<T>::type&&>(t);
}std::forward: conservar la categoría
En una plantilla que usa una referencia de reenvío (T&&), std::forward<T>(x) convierte x de nuevo a su categoría original (lvalue o rvalue). Se usa para el reenvío perfecto.
template <typename T>
void wrapper(T&& arg) {
target(std::forward<T>(arg)); // forwards as lvalue or rvalue depending on T
}Por qué es necesario el reenvío
Dentro de la plantilla, el parámetro tiene un nombre, por lo que es un lvalue aunque la persona que llama haya pasado un rvalue. std::forward recupera la categoría original.
Sin std::forward
Sin forward, todos los argumentos se pasarían como lvalues dentro del envoltorio, anulando cualquier semántica de movimiento que quisiera la persona que llama.
template <typename T>
void wrapper(T&& arg) {
target(arg); // always lvalue — wrong
}Especificar siempre el parámetro de plantilla de forward
std::forward<T> requiere el argumento de plantilla explícito. Sin él, el comportamiento sería incorrecto.
Ejemplo de reenvío perfecto
Una función de fábrica que reenvía los argumentos del constructor conserva las distinciones entre rvalue y lvalue para mejorar la eficiencia.
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}Mover una sola vez
Cada objeto debería moverse como máximo una vez. Después del movimiento, queda en un estado válido pero no especificado; normalmente se reasigna o se destruye. Usar un objeto desde el que se ha movido algo sin reasignarlo primero puede provocar errores sutiles.
Reglas prácticas
Modelo mental rápido:
- Si tiene un tipo concreto y quiere moverlo →
std::move - Si tiene un parámetro de plantilla y quiere conservar su categoría →
std::forward<T>
Comprobación rápida
Dentro de una función de plantilla con el parámetro T&& arg, ¿cómo reenvía arg conservando su categoría de lvalue o rvalue?
Resumen
std::move convierte incondicionalmente a rvalue; úselo con objetos concretos de cuyos recursos quiera apropiarse. std::forward<T> conserva la categoría de valor dentro de las plantillas genéricas; úselo para el reenvío perfecto.
Preguntas frecuentes
¿La lección «std::move y std::forward» es gratis?
Sí — el texto completo de «std::move y std::forward» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C++ Academy, actualiza a CoddyKit PRO. El curso de C++ Academy incluye 4 lecciones en total.
¿Qué aprenderé en «std::move y std::forward»?
Convierta lvalues en rvalues con std::move y conserve la categoría de valor con std::forward. Practicas C++ Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C++ Academy?
No se requiere experiencia previa. C++ Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «std::move y std::forward»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C++ Academy?
Sí. Cada lección de C++ Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Lvalue frente a rvalue: la diferencia
- Referencias rvalue y sintaxis &&
- std::move y std::forward
- Constructores de movimiento y asignación de movimiento