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 claseX
se define como eliminado (8.4.3) siX
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, yX
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 claseX
se define como eliminado (8.4.3) siX
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
puedewith_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 deunique_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);
}