std:: move
|
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) |
|
(C++11)
|
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) |