c++ c++11 variable-assignment swap move-semantics

c++ - ¿Qué puedo hacer con un objeto movido desde?



c++11 variable-assignment (2)

¿El estándar define con precisión qué puedo hacer con un objeto una vez que se ha movido? Solía ​​pensar que todo lo que puedes hacer con un objeto movido es destruirlo, pero eso no sería suficiente.

Por ejemplo, tome el swap plantilla de función como se define en la biblioteca estándar:

template <typename T> void swap(T& a, T& b) { T c = std::move(a); // line 1 a = std::move(b); // line 2: assignment to moved-from object! b = std::move(c); // line 3: assignment to moved-from object! }

Obviamente, debe ser posible asignar objetos movidos, de lo contrario las líneas 2 y 3 fallarían. Entonces, ¿qué más puedo hacer con los objetos movidos? ¿Dónde puedo encontrar exactamente estos detalles en el estándar?

(Por cierto, ¿por qué es T c = std::move(a); lugar de T c(std::move(a)); en la línea 1?


17.6.5.15 [lib.types.movedfrom]

Los objetos de tipos definidos en la biblioteca estándar de C ++ se pueden mover desde (12.8). Las operaciones de movimiento pueden especificarse explícitamente o generarse implícitamente. A menos que se especifique lo contrario, dichos objetos movidos se colocarán en un estado válido pero no especificado.

Cuando un objeto está en un estado no especificado, puede realizar cualquier operación en el objeto que no tenga condiciones previas. Si hay una operación con condiciones previas que desea realizar, no puede realizar esa operación directamente porque no sabe si el estado no especificado del objeto satisface las condiciones previas.

Ejemplos de operaciones que generalmente no tienen condiciones previas:

  • destrucción
  • asignación
  • observadores const como get , empty , size

Ejemplos de operaciones que generalmente tienen precondiciones:

  • desreferencia
  • pop_back

Esta respuesta ahora aparece en formato de video aquí: http://www.youtube.com/watch?v=vLinb2fgkHk&t=47m10s


Los objetos movidos desde-existen en un estado no especificado, pero válido. Esto sugiere que, si bien el objeto podría no ser capaz de hacer mucho más, todas sus funciones miembro deberían exhibir un comportamiento definido, incluido el operator= y todos sus miembros en un estado definido, y aún así requiere destrucción. El estándar no proporciona definiciones específicas porque sería exclusivo de cada UDT, pero es posible que pueda encontrar especificaciones para los tipos estándar. Algunos contenedores similares son relativamente obvios: simplemente mueven su contenido y un contenedor vacío es un estado válido bien definido. Las primitivas no modifican el objeto movido desde.

Nota al margen: creo que es T c = std::move(a) modo que si el constructor de movimientos (o el constructor de copias si no se proporciona movimiento) es explícito, la función fallará.