Namespaces
Variants

std:: move

From cppreference.net
Utilities library
Definido en el 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 ser "movido desde", es decir, permitiendo la transferencia eficiente de recursos desde t a otro objeto.

En particular, std::move produce una expresión xvalue que identifica su argumento t . Es exactamente equivalente a un static_cast a un tipo de referencia a valor derecho.

Contenidos

Parámetros

t - el objeto a ser movido

Valor de retorno

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

Notas

Las funciones que aceptan parámetros de referencia a valor derecho (incluyendo constructores de movimiento , operadores de asignación de movimiento , y funciones miembro regulares como std::vector::push_back ) son seleccionadas, mediante resolución de sobrecarga , cuando se las llama con argumentos de valor derecho (ya sea prvalues como un objeto temporal o xvalues como los producidos por std::move ). Si el argumento identifica un objeto que posee recursos, estas sobrecargas tienen la opción, pero no la obligación, de mover cualquier recurso mantenido por el argumento. Por ejemplo, un constructor de movimiento de una lista enlazada podría copiar el puntero a la cabeza de la lista y almacenar nullptr en el argumento en lugar de asignar y copiar nodos individuales.

Los nombres de rvalue reference son lvalues y deben convertirse a xvalues para poder enlazarse con las sobrecargas de función que aceptan parámetros de rvalue reference, razón por la cual move constructors y move assignment operators normalmente utilizan std::move :

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

Una excepción es cuando el tipo del parámetro de la función es una referencia de reenvío (que parece una referencia a valor derecho a un parámetro de plantilla de tipo), en cuyo caso se utiliza std::forward en su lugar.

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", lo que significa que las invariantes de clase del objeto se mantienen (por lo que las funciones sin precondiciones, como el operador de asignación, pueden usarse de forma segura en el objeto después de haber sido movido):

std::vector<std::string> v;
std::string str = "example";
v.push_back(std::move(str)); // str ahora es válida pero no especificada
str.back(); // comportamiento indefinido si size() == 0: back() tiene una precondición !empty()
if (!str.empty())
    str.back(); // OK, empty() no tiene precondición y se cumple la precondición de back()
str.clear(); // OK, clear() no tiene precondiciones

Además, las funciones de la biblioteca estándar llamadas con argumentos xvalue pueden asumir que el argumento es la única referencia al objeto; si fue construido desde un lvalue con std::move , no se realizan verificaciones de aliasing. Sin embargo, la auto-asignación por movimiento de tipos de la biblioteca estándar garantiza colocar el objeto en un estado válido (pero usualmente no especificado):

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

Ejemplo

#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main()
{
    std::string str = "Salut";
    std::vector<std::string> v;
    // utiliza la sobrecarga push_back(const T&), lo que significa
    // que incurriremos en el costo de copiar str
    v.push_back(str);
    std::cout << "After copy, str is " << std::quoted(str) << '\n';
    // utiliza la sobrecarga push_back(T&&) de referencia a valor derecho,
    // lo que significa que no se copiarán cadenas; en su lugar, los contenidos
    // de str se moverán al vector. Esto es menos
    // costoso, pero también significa que str podría quedar vacío.
    v.push_back(std::move(str));
    std::cout << "After move, str is " << std::quoted(str) << '\n';
    std::cout << "The contents of the vector are {" << std::quoted(v[0])
              << ", " << std::quoted(v[1]) << "}\n";
}

Salida posible:

After copy, str is "Salut"
After move, str is ""
The contents of the vector are {"Salut", "Salut"}

Véase también

(C++11)
reenvía un argumento de función y utiliza el argumento de plantilla de tipo para preservar su categoría de valor
(plantilla de función)
convierte el argumento a un xvalue si el constructor de movimiento no lanza excepciones
(plantilla de función)
(C++11)
mueve un rango de elementos a una nueva ubicación
(plantilla de función)