Espacios de nombres
Variantes
Acciones

std::move

De cppreference.com
< cpp‎ | utility
 
 
Biblioteca de servicios
Servicios generales
Operadores relacionales (en desuso en C++20)
 
Definido en el archivo de encabezado <utility>
template< class T >
typename std::remove_reference<T>::type&& move( T&& t ) noexcept;
(desde C++11)
(hasta C++14)
template< class T >
constexpr std::remove_reference_t<T>&& move( T&& t ) noexcept;
(desde C++14)

std::move se utiliza para indicar que un objeto t puede "moverse", es decir, permite la transferencia eficiente de recursos de t a otro objeto.

En particular, std::move produce una expresión x-valor que identifica su argumento t. Es exactamente equivalente a una conversión estática a un tipo referencia r-valor.

Contenido

[editar] Parámetros

t - El objeto a ser movido.

[editar] Valor de retorno

static_cast<typename std::remove_reference<T>::type&&>(t)

[editar] Notas

Las funciones que aceptan parámetros de referencia r-valor (incluidos los constructores de movimiento, operadores de asignación de movimiento y funciones miembro regulares como std::vector::push_back) son seleccionadas, por la resolución de sobrecarga, cuando son llamadas con argumentos r-valor (ya sea pr-valores, como un objeto temporal, o x-valores, como el producido por std::move). Si el argumento identifica un objeto propietario de recursos, estas sobrecargas tienen la opción, pero no están obligadas, a "mover" los recursos que tiene el argumento. Por ejemplo, un constructor de movimiento de una lista enlazada podría copiar el puntero al encabezado de la lista y almacenar nullptr en el argumento en lugar de asignar y copiar nodos individuales.

Los nombres de las variables referencia r-valor son l-valores y tienen que convertirse a x-valores para ser vinculadas a las sobrecargas de función que acepten parámetros a referencia r-valor, que es la razón por la que los constructores de movimiento y los operadores de asignación de movimiento habitualmente usan std::move:

// Constructor de movimiento simple
A(A&& arg) : miembro(std::move(arg.miembro)) // la expresión "arg.miembro" es un l-valor
{} 
// Operador de asignación de movimiento simple
A& operator=(A&& other) {
     miembro = std::move(other.miembro);
     return *this;
}

Una excepción es cuando el tipo del parámetro de función es una referencia r-valor al tipo del parámetro de plantilla ("referencia de reenvío" o "referencia universal"), en cuyo caso se usa std::forward.

A menos que se especifique lo contrario, todos los objetos de la biblioteca estándar que han sido movidos se colocan en un estado válido pero no especificado. Es decir, solo las funciones sin precondiciones, como el operador de asignación, se pueden usar de forma segura en el objeto después de que éste se haya movido:

std::vector<std::string> v;
std::string str = "ejemplo";
v.push_back(std::move(str)); // str es ahora válido pero no especificado
str.back(); // comportamiento indefinido si size() == 0: back() tiene una precondición !empty()
str.clear(); // de acuerdo, clear() no tiene precondiciones

Además, las funciones de la biblioteca estándar llamadas con argumentos x-valor pueden asumir que el argumento es la única referencia al objeto; si se construyó a partir de un l-valor con std::move, no se realizan comprobaciones de alias. En particular, esto significa que los operadores de asignación de movimiento de la biblioteca estándar no tienen que realizar comprobaciones de autoasignación:

std::vector<int> v = {2, 3, 3};
v = std::move(v); // el valor de v no está especificado

[editar] Ejemplo

#include <iostream>
#include <utility>
#include <vector>
#include <string>
 
int main()
{
    std::string str = "Hola";
    std::vector<std::string> v;
 
    // usa la sobrecarga push_back(const T&), que quiere decir
    // que incurriremos en el costo de copiar a str
    v.push_back(str);
    std::cout << "Después de la copia, str es \"" << str << "\"\n";
 
    // usa la sobrecarga referencia r-valor push_back(T&&), 
    // que significa que ninguna cadena se copiará; en su lugar,
    // el contenido de str se moverá dentro del vector.  Esto es menos
    // caro, pero también significa que str ahora podría estar vacío.
    v.push_back(std::move(str));
    std::cout << "Después del movimiento, str es \"" << str << "\"\n";
 
    std::cout << "El contenido del vector es \"" << v[0]
                                         << "\", \"" << v[1] << "\"\n";
}

Posible salida:

Después de la copia, str es "Hola"
Después del movimiento, str es ""
El contenido del vector es "Hola", "Hola"

[editar] Véase también

(C++11)
Reenvía una función argumento
(plantilla de función) [editar]
Obtiene una referencia r-valor si el constructor de movimiento no lanza una excepción
(plantilla de función) [editar]
(C++11)
Mueve una serie de elementos a una nueva ubicación.
(plantilla de función) [editar]