ejemplo - ¿Por qué C++ le permite mover clases que contienen objetos con operaciones de movimiento eliminadas?
iterator c++ ejemplo (1)
Note la diferencia entre las dos clases. Para TestNonMovable
(caso 2), declara explícitamente que el constructor de movimiento se delete
. Con TestNonMovable tnm2 = std::move(tnm);
el constructor de movimiento eliminado se selecciona en la resolución de sobrecarga y luego causa el error.
Para SomeClass
(caso 1), no declara explícitamente el constructor de mover y copiar. El constructor de copia se declarará y definirá implícitamente, pero el constructor de movimiento se declarará y definirá implícitamente como eliminado porque tiene un miembro de datos no móvil. Tenga en cuenta que el constructor de movimientos declarado implícitamente eliminado no participará en la resolución de sobrecarga . Con SomeClass sc2 = std::move(sc1);
, se selecciona el constructor de copia y luego el código funciona bien. La referencia rvalue devuelta desde std::move
podría estar vinculada a lvalue-reference a const (es decir, const SomeClass&
).
El constructor de movimiento declarado implícitamente eliminado se ignora por la resolución de sobrecarga (de lo contrario, evitaría la inicialización de la copia desde el valor). (desde C ++ 14)
BTW: std::move sí está permitido en ambos casos. No realiza la operación de movimiento , simplemente convierte el argumento a rvalue. La operación de traslado ocurre en la construcción en ambos casos.
¿Por qué se me permite usar std::move
en una clase que contiene campos de un tipo con semántica de movimiento eliminada (caso 1), pero no puedo usarlo en una instancia de dicha clase (caso 2)?
Entiendo el caso 2. He eliminado explícitamente el constructor de movimientos, por lo que recibo un error si intento moverlo. Pero espero que este también sea el caso en el caso 1, donde esa clase también se está moviendo.
class TestNonMovable {
std::string ss;
public:
TestNonMovable(){}
TestNonMovable(const TestNonMovable&) {}
TestNonMovable(TestNonMovable&&) = delete;
};
class SomeClass {
TestNonMovable tnm;
};
int main() {
// case1: This compiles, my understanding is that for SomeClass::tnm compiler will use copy constrctor
SomeClass sc1;
SomeClass sc2 = std::move(sc1);
// case2: This does not compile, move constructor is explicitly deleted, compiler will not try using copy constructor
TestNonMovable tnm;
TestNonMovable tnm2 = std::move(tnm); //error: use of deleted function ''TestNonMovable::TestNonMovable(TestNonMovable&&)''
}