2012-01-24 17 views
6

Me gustaría tener un vector de unique_ptr como miembro de una clase que estoy haciendo.¿Cómo declarar un vector de unique_ptr como miembro de datos de clase?

class Foo { 
    [...] 

private: 
    vector<unique_ptr<Bar>> barList; 
} 

Pero entonces comienza a recibir mensajes de error crípticos de la VS2010 compilador:

error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 

Junto con un puñado de líneas de error por debajo de lo que sumergirse en la implementación de std::_Copy_impl<> de Microsoft ...

Cambié la declaración del miembro a

vector<unique_ptr<Bar>>* barList; 

Y compila. Pero no puedo evitar preguntarme por qué no puedo hacerlo de la manera que originalmente quería. Para las muecas, he intentado esto y funciona bien:

vector<Bar> barList; 

Pero ahora que pierda la comodidad de unique_ptr. ¡Quiero mi pastel y también quiero comerlo!

+0

Estaba viendo http://stackoverflow.com/questions/8553464/vector-as-a-class-member y la respuesta parece pensar que declarar un 'vector' como lo hice está bien hacerlo. Por alguna razón, sin embargo, parece desencadenar copias ilegales al agregar la parte 'unique_ptr'. –

+1

¿Cómo son el constructor de copias y el operador de asignación? –

+0

Asignación privada, pero el constructor de copia fue el culpable. Cambié de 'unique_ptr' a' shared_ptr' cuando me di cuenta de que estaba usando la semántica de propiedad incorrecta. –

Respuesta

10

El problema aquí es que en algún lugar, su código está intentando llamar al operador "copia-asignación" de Foo.

Esto hace que el compilador intente generar un operador de copia-asignación que llama a los operadores de copia-asignación de todos los subobjetos de Foo. Eventualmente, esto lleva a un intento de copiar un unique_ptr, una operación que no es posible.

+0

Gracias por señalar esto. El compilador me estaba engañando porque el error hacía referencia a la declaración del miembro y no mencionaba el código ofensivo que causaba la copia. Me imagino que esto es una deficiencia en VS2010 y espero que mejore con lanzamientos más nuevos. Mi clase 'Foo' tiene un constructor de copia, y yo estaba tratando de copiar el vector de la fuente' Foo'. La propiedad compartida parece ser la mejor solución, por lo que cambiar a 'shared_ptr' hizo el truco. –

+1

Parece un error en VS2010. Recibo este error incluso si mi código nunca intenta llamar a la asignación de copia. Desactivar el operador = declarando como privado (por lo tanto, = eliminar no es compatible) resuelve el problema. – tr3w

-2

No se puede usar unique_ptr en el vector porque la implementación del vector depende en gran medida de los operadores de asignación de valores, que es privado en unique_ptr. Use shared_ptr desde boost u otra implementación inteligente de ptr desde C++ 11.

+6

'unique_ptr' funciona muy bien en un' vector'. [Ver.] (Http://ideone.com/riLhp) –

+0

Se requiere que los contenedores de C++ 11 funcionen con tipos de solo movimiento como 'unique_ptr'. – bames53

+0

Quise decir la forma en que lo usó. Pero aún así, gracias, no sabía acerca de emplace_back. – aambrozkiewicz

4

unique_ptr no tiene semántica de copia, por lo que no puede utilizar ningún método que pueda copiar el objeto contenido. Usted puede hacer esto con referencias rvalue usando std::move en el lugar (s) que está tratando de hacer una copia. Sin ver tu código, no puedo decir dónde estaría.

Si se compila en la segunda forma o no ejercitaste el mismo código o hay un error en el compilador. Ambos deberían fallar de la misma manera.

Su tercer ejemplo, almacenar por valor es la forma más sencilla a menos que sus objetos sean grandes y caros de almacenar/copiar por valor.

+1

'auto_ptr' es el que no obedece la semántica de copia normal,' unique_ptr' simplemente no ** tiene ** copia semántica – Grizzly

+0

Las respuestas de Your's y Mankarse son muy similares. El suyo, sin embargo, me hizo darme cuenta de que tenía que ir a la caza de brujas por el código ofensivo (tu respuesta abordaba ese tema de manera más sutil). Sin embargo, ambos merecen la respuesta aceptada. ¡Gracias por la ayuda! –

2

Suele faltar un std::move(iUniquePtr) en algún lugar (por ejemplo, al usar push_back).

0

extractos An desde www.cplusplus.com

std::unique_ptr::operator= 

asignación unique_ptr El objeto adquiere la propiedad del contenido de x, incluyendo tanto el puntero almacenado y el Deleter almacenado (junto con la responsabilidad de eliminar el objeto en algún momento). Cualquier objeto propiedad del objeto unique_ptr antes de que se elimine la llamada (como si se llamara el destructor de unique_ptr).

Pero hay también una advertencia:

Esta página describe una característica introducida por la última revisión del estándar de C++ (2011). Es posible que los compiladores antiguos no lo admitan.

MSVC 2010 define operator= como privado (no se puede copiar) pero admite el método swap.

Cuestiones relacionadas