studio programacion para móviles libros gratis español edición desarrollo desarrollar curso aprende aplicaciones c++ c++11 user-defined-functions move-semantics implicit-declaration

c++ - para - manual programacion android español pdf



¿Por qué el constructor de movimientos no se declara ni se elimina con el sonido? (2)

C ++ 11, o más bien n3485, [class.copy] / 9:

Si la definición de una clase X no declara explícitamente un constructor de movimiento, uno se declarará implícitamente como predeterminado si y solo si

  • X no tiene un constructor de copia declarado por el usuario,
  • X no tiene un operador de asignación de copia declarado por el usuario,
  • X no tiene un operador de asignación de movimiento declarado por el usuario,
  • X no tiene un destructor declarado por el usuario, y
  • el constructor de movimiento no se definiría implícitamente como eliminado.

y / 11:

Un constructor de copia / movimiento declarado implícitamente es un miembro inline public de su clase. Un constructor predeterminado de copiar / mover para una clase X se define como eliminado (8.4.3) si X tiene:

  • [...]
  • para el constructor de copia, un miembro de datos no estáticos de tipo de referencia rvalue, o
  • para el constructor de movimientos, un miembro de datos no estáticos o una clase base directa o virtual con un tipo que no tiene un constructor de movimientos y no se puede copiar de forma trivial.

Como with_copy no se puede with_copy forma trivial, foo no tendrá ningún constructor de movimiento (se definiría como eliminado, por lo tanto, no se declarará implícitamente).

C ++ 1y, o más bien github repo commit e31867c0 del 2013-11-12; incorporando DR1402 :

/ 9:

Si la definición de una clase X no declara explícitamente un constructor de movimiento, uno se declarará implícitamente como predeterminado si y solo si

  • X no tiene un constructor de copia declarado por el usuario,
  • X no tiene un operador de asignación de copia declarado por el usuario,
  • X no tiene un operador de asignación de movimiento declarado por el usuario, y
  • X no tiene un destructor declarado por el usuario.

y / 11:

Un constructor de copia / movimiento declarado implícitamente es un miembro inline public de su clase. Un constructor predeterminado de copiar / mover para una clase X se define como eliminado (8.4.3) si X tiene:

  • [...]
  • para el constructor de copia, un miembro de datos no estáticos de tipo de referencia rvalue.

Un constructor de movimiento predeterminado que se define como eliminado se ignora por la resolución de sobrecarga (13.3, 13.4).

Aquí, foo tendrá un constructor de movimientos.

Considera las siguientes clases.

struct with_copy { with_copy() = default; with_copy(with_copy const&) {} with_copy& operator=(with_copy const&) { return *this; } }; struct foo { with_copy c; std::unique_ptr<int> p; };

  • ¿Tiene with_copy un constructor de copia? Sí. Fue explícitamente definido.
  • ¿Tiene with_copy un constructor de movimiento? No. El constructor de copia explícita impide que se genere.
  • ¿ with_copy tiene un constructor de movimiento eliminado? No. No tener un constructor de movimiento no es lo mismo que tener uno eliminado. Un constructor de movimiento eliminado haría un intento de moverse mal formado en lugar de degenerar en una copia.
  • ¿ with_copy puede with_copy with_copy? Sí. Su copia constructor se utiliza para copias.
  • ¿Es with_copy móvil? Sí. Su constructor de copia se utiliza para movimientos.

... y ahora los difíciles.

  • ¿ foo tiene un constructor de copia? Sí. Tiene una eliminada, ya que su definición predeterminada no estaría bien formada debido a la invocación del constructor de copia eliminada de unique_ptr .
  • ¿ foo tiene un constructor de movimiento? GCC dice que sí, clang dice que no.
  • ¿ foo tiene un constructor de movimiento eliminado? Tanto GCC como clang dicen que no.
  • Es foo copiable? No. Se elimina su constructor de copia.
  • ¿Es foo móvil? GCC dice que sí, clang dice que no.

(El comportamiento es similar cuando se considera la asignación en lugar de la construcción.)

Por lo que puedo ver, GCC es correcta. foo debería tener un constructor de movimientos que realice un movimiento en cada miembro, que en el caso de with_copy degenera en una copia. El comportamiento de Clang parece bastante ridículo: tengo un agregado con dos miembros móviles y, sin embargo, mi agregado es un ladrillo inamovible.

Quien tiene razon


No estoy muy seguro de lo que probaste, pero es seguro que se pueden asignar y mover de forma constructiva. Es cierto que esto no dice nada acerca de que un constructor de movimientos o una asignación de movimientos sean accesibles, solo que la construcción o asignación de un valor de ralor funciona. Tanto clang (clang versión 3.5 (trunk 196718)) como gcc (gcc versión 4.9.0 20131031 (experimental) (GCC)) están de acuerdo con esta evaluación. Esta es la fuente completa que probé:

#include <iostream> #include <type_traits> #include <memory> struct with_copy { with_copy() = default; with_copy(with_copy const&) {} with_copy& operator=(with_copy const&) { return *this; } }; struct foo { with_copy c; std::unique_ptr<int> p; }; int main() { std::cout << "move constructible: " << std::is_move_constructible<foo>::value << ''/n''; std::cout << "move assignable: " << std::is_move_assignable<foo>::value << ''/n''; foo f0; foo f1 = std::move(f0); f0 = std::move(f1); }