2012-05-31 21 views
6

Imagine un class C que tiene un miembro variable m_MyList de tipo std::vector en el que quiero almacenar objetos del tipo MyClass. C tiene dos funciones que agregan o quitan objetos en m_MyList. m_MyList también debe hacerse accesible para los consumidores de C ya que necesitan leer la colección de objetos MyClass. El lector externo de la colección no tendrá medios para cambiar la colección, por lo tanto, los objetos MyClass son propiedad solo de C.¿Debo usar std :: unique_ptr <T> en una variable de miembro std :: vector en mi clase?

Ahora mi pregunta: En el estilo C++ 11, ¿cuál es la mejor T para almacenar en el vector? Las posibilidades parecen ser:

  • std::vector<MyClass>
  • std::vector<MyClass*>
  • std::vector<unique_ptr<MyClass>>, utilizando std:move para empujar el unique_ptr en el vector
+3

La solución 'unique_ptr' realmente no le compra nada, a menos que los objetos no puedan copiarse. La versión del puntero sin procesar es francamente dañina. Simplemente busque la solución simple – jalf

+0

¿Qué tan grande es un objeto 'MyClass' y cuántos está planeando almacenar? ¿Habrá muchas inserciones individuales? – RedX

Respuesta

13

Si los MyClass objetos son propiedad de C, entonces la mejor la opción sería la más simple:

std::vector<MyClass> 

La única razón que pude ver para usar std::unique_ptrs aquí es si necesita mantener los punteros a una clase base para el polimorfismo. En este caso, unique_ptrs sirve para liberar recursos después de la destrucción del vector. Pero entonces la interfaz C no debe transferir la propiedad a los clientes.

+5

'MyClass' podría ser un objeto costoso de mover/copiar. El uso de un puntero le permite cambiar el tamaño del vector sin tener que copiar mucha memoria. –

+1

@ edA-qamort-ora-y eso es cierto, pero es independiente de la propiedad y los clientes, y así sucesivamente, así que asumí que la consideración estaba más allá del alcance de la pregunta. – juanchopanza

+1

La otra razón para utilizar cualquier tipo de tipo de referencia como miembro de una clase es asegurarse de que el encabezado no expone los detalles de esos miembros, mientras que el archivo de unidad (cpp) sí lo sabe. Es bueno para el aislamiento en realidad. Aquí, el vector requiere que se defina MyClass antes de que se defina el miembro. Entonces debes incluir el código de MyClass. En algunos casos, no quieres eso. Dicho esto, tiene una memoria diferente y costos de administración, por lo que la elección es muy específica del contexto. – Klaim

11

Los punteros sin formato (std::vector<MyClass*>) son incorrectos si C posee los objetos. Los otros dos son bastante similares con las siguientes compensaciones:

  • std::vector<MyClass> - requiere MyClass ser copiable y/o mover-capaz
  • std::vector<unique_ptr<MyClass>> - requiere asignaciones dinámicas (adicionales)

El el tipo de operaciones que se realizan en el contenedor también puede ser relevante. Para tomar un ejemplo extremo, si MyClass es grande y el contenedor se baraja repetidamente, unique_ptr sería la mejor opción.

+0

se coloca cada elemento de un 'std :: vECTOR' en la tienda libre, por lo que dice "requiere asignaciones dinámicas" como si fuera una cosa mala es una especie de un término equivocado aquí ... – rubenvb

+2

@rubenvb: el vector sólo requiere una asignación dinámica a la vez (o brevemente 2 durante la reasignación). Por lo tanto, no requiere asignaciones dinámicas ;-) Si 'MyClass' es lo suficientemente pequeño, notará la diferencia con el tiempo. Supongo que sería mejor decir que "requiere más sobrecarga en asignaciones dinámicas". Es algo malo si está escribiendo código adicional con el único propósito de desperdiciar memoria. * Podría * ser algo malo si es 'MyClass' nothrow construible, y le presentaremos las asignaciones dinámicas en lugares que de otro modo no suceder, introduciendo así excepciones. –

+0

asignación dinámica de cada objeto individual no sólo requiere más memoria, aumenta la fragmentación y la causa más fallos de caché de datos. En la mayoría de los códigos, será totalmente inadmisible, pero, como dice Steve, no escriba más para empeorar el código. –

Cuestiones relacionadas