¿Qué es std::move() y cuándo debería usarse?
- ¿Qué es?
- ¿Qué hace?
- ¿Cuándo debería usarse?
Se agradecen buenos enlaces.
1. "¿Qué es?"
Aunque std::move()
técnicamente es una función, yo diría que en realidad no es una función . Es una especie de conversor entre las formas en que el compilador considera el valor de una expresión.
2. "¿Qué hace?"
Lo primero que hay que tener en cuenta es que std::move()
en realidad no mueve nada . Cambia una expresión de ser un valor l (como una variable con nombre) a un valor x . Un valor x le dice al compilador:
Puedes saquearme, mover cualquier cosa que tenga y usarla en otro lugar (ya que de todos modos seré destruido pronto)".
en otras palabras, cuando usas std::move(x)
, estás permitiendo que el compilador canibalice x
. Por lo tanto, si x
tiene, digamos, su propio búfer en la memoria, después de std::move()
ejecutar el compilador, puede hacer que otro objeto sea propietario.
También puedes moverte de un valor pr (como un valor temporal que estás pasando), pero esto rara vez es útil.
3. "¿Cuándo se debe utilizar?"
Otra forma de hacer esta pregunta es "¿Para qué canibalizaría los recursos de un objeto existente?" bueno, si estás escribiendo código de aplicación, probablemente no estarás jugando mucho con los objetos temporales creados por el compilador. Básicamente, haría esto en lugares como constructores, métodos de operador, funciones similares a algoritmos de biblioteca estándar, etc., donde los objetos se crean y destruyen automáticamente de forma frecuente. Por supuesto, eso es sólo una regla general.
Un uso típico es "mover" recursos de un objeto a otro en lugar de copiarlos. @Guillaume enlaza a esta página que tiene un breve ejemplo sencillo: intercambiar dos objetos con menos copia.
template <class T>
swap(T& a, T& b) {
T tmp(a); // we've made a second copy of a
a = b; // we've made a second copy of b (and discarded a copy of a)
b = tmp; // we've made a second copy of tmp (and discarded a copy of b)
}
usar move te permite intercambiar los recursos en lugar de copiarlos:
template <class T>
swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
Piense en lo que sucede cuando T
es, digamos, vector<int>
de tamaño n. En la primera versión lees y escribes 3*n elementos, en la segunda versión básicamente lees y escribes solo los 3 punteros a los búferes de los vectores, más los tamaños de los 3 búferes. Por supuesto, la clase T
necesita saber cómo hacer el movimiento; su clase debe tener un operador de asignación de movimiento y un constructor de movimiento para la clase T
para que esto funcione.
Página de Wikipedia sobre referencias de valores R de C++ 11 y constructores de movimientos
- En C++11, además de los constructores de copia, los objetos pueden tener constructores de movimiento.
(Y además de copiar operadores de asignación, tienen operadores de asignación de movimiento). - El constructor de movimiento se utiliza en lugar del constructor de copia, si el objeto tiene el tipo "rvalue-reference" (
Type &&
). std::move()
es una conversión que produce una referencia de valor a un objeto, para permitir moverse desde él.
Es una nueva forma en C++ de evitar copias. Por ejemplo, al usar un constructor de movimiento, a std::vector
podría simplemente copiar su puntero interno a los datos al nuevo objeto, dejando el objeto movido en un estado movido desde y, por lo tanto, sin copiar todos los datos. Esto sería válido para C++.
Intente buscar en Google semántica de movimientos, rvalue, reenvío perfecto.