¿Cómo eliminar un elemento de un vector cuando el objeto contenedor contiene un unique_ptr?
Frecuentes
Visto 988 veces
3
Noté que no es posible eliminar un elemento de un vector cuando el tipo contenedor contiene un unique_ptr.
Por ejemplo esta clase:
class Bar
{
std::unique_ptr<int> pointerTest;
Bar(Bar &bar) {};
public:
Bar() { pointerTest = std::unique_ptr<int>(new int); }
Bar(Bar &&bar) { this->pointerTest = move(bar.pointerTest); }
void testFunc() { pointerTest.release(); }
};
Esto no funciona con este uso:
int main()
{
vector<Bar> test123;
Bar foo;
test123.push_back(move(foo));
test123.erase(test123.begin());
}
//Error 1 error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 611 1 testing
El código funcionará cuando solo llame a los métodos de objetos en lugar de borrar:
for (auto &item : test123)
item.testFunc();
¿Cuál es la razón por la que no puedo usar el borrado en el vector y cómo podría resolverlo?
2 Respuestas
3
El problema es que tu clase no sigue correctamente la regla del tres/cinco. Defina un constructor de copiar y mover, pero no un operador de asignación de movimiento. Lo que significa que no se genera ningún operador de asignación de movimiento y el operador de asignación de copia predeterminado siempre se usa al asignar. Sin embargo, dado que su clase tiene un miembro no copiable, el operador de asignación de copia predeterminado se define como eliminado, por lo que obtiene un error al usarlo.
Y se invoca porque la eliminación de elementos de un vector provoca un desplazamiento (es decir, asignación) de todos los elementos siguientes del vector. Esa sería una asignación de movimiento normalmente, pero dado que eso no está definido (y no se genera automáticamente) en su clase, se invoca la asignación de copia y falla.
Veo que está utilizando Visual Studio, por lo que un constructor de movimiento/operador de asignación de movimiento no se generaría automáticamente de todos modos (VS aún no es compatible con esta parte del estándar). Entonces, para solucionar esto de una manera compatible con VS, defina un operador de asignación de movimiento. Y podría ser una buena idea eliminar el constructor de copia mientras lo hace: la clase parece un excelente ejemplo de una clase no copiable.
respondido 22 nov., 13:16
1
El mensaje de error de g ++ 4.8.1 es bastante claro:
trash.cpp:9:11: nota: 'Bar& Bar::operator=(const Bar&)' se declara implícitamente como eliminado porque 'Bar' declara un constructor de movimiento o un operador de asignación de movimiento
Al agregar el operador de movimiento, el problema se resuelve:
class Bar
{
std::unique_ptr<int> pointerTest;
Bar(const Bar &);
public:
Bar() { pointerTest = std::unique_ptr<int>(new int); }
Bar(Bar &&bar) : pointerTest( move(bar.pointerTest)) {}
Bar& operator=(Bar&& bar){ pointerTest = std::move(bar.pointerTest); return *this;}
void testFunc() { pointerTest.release(); }
};
respondido 22 nov., 13:16
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ vector visual-studio-2013 unique-ptr or haz tu propia pregunta.
FWIW, su código se compila bajo g ++ 4.6. - user4815162342
Puedo arreglar esto en GCC 4.8 eliminando el constructor de movimientos innecesarios y el constructor de copias extrañas. No sé exactamente cuál es el problema, o si eso lo solucionará para su compilador. - Mike Seymour
Extraño, no puedo compilar esto en Visual Studio 2013 con o sin el constructor de copiar y mover. @Mike Seymour ¿Qué está conectado con esos constructores? - Dagob
el error es claro, intenta llamar al operador de asignación de
unique_ptr
que toma una referencia const lvalue, que se elimina de unique_ptr. su código nunca lo llama, tal vez el problema esté en algún lugar de su código que no muestra. quizás el destructor de Bar. - yngccc@yngum El código en esta pregunta es el código completo que compilo. Puedes encontrarlo aquí también: pastebin.com/jHNgSUi9. - Dagob