2010-09-29 24 views
16

Necesito un contenedor de punteros. ¿Recomendaría boost::ptr_vector<T> o std::vector<boost::shared_ptr<T> >? (¿O algo más?)¿Debo usar boost :: ptr_vector <T> o vector <boost :: shared_ptr <T>>?

Si eso es de interés, mi estructura de datos real es relativamente complicada (ver here) y actualmente almacena objetos, no punteros, pero me gustaría cambiar eso (usando contenedores de puntero), en orden para deshacerse de copias innecesarias:

typedef std::multimap<Foo0, std::map<int, double> > VecElem; 
std::vector<VecElem> vec; 
+0

¿Dónde ocurre esta copia innecesaria? –

+0

@Idan: Cada vez que insertas algo en el vector o multimapa desde arriba. – Frank

+3

@Idan: cuando tiene un contenedor que almacena punteros, solo se copiará el puntero al agregar datos, cuando almacene objetos, se copiarán los objetos reales. Este es un problema cuando se trata de objetos que son caros de copiar. – sbi

Respuesta

30

quién pertenece el objeto? Si el contenedor posee los objetos (es decir, los objetos no deben vivir más tiempo que el contenedor), utilice ptr_vector. De lo contrario, utilice un vector de shared_ptr s. Los contenedores de biblioteca estándar (como std::vector o std::list) poseen los objetos que contienen, por lo que la semántica de ptr_vector es más cercana a eso.

+0

Pregunta adicional: ¿es un 'vector' de' unique_ptr' lo mismo que 'ptr_vector'? –

+0

@Didier: No sé lo suficiente sobre 'unique_ptr' para responder esa pregunta. Sin embargo, el 'ptr_vector' tendrá menos sobrecarga (como señala @sbi en su respuesta). –

+8

@Didier: no, 'ptr_vector' permite copiar el' vector', que copia profundamente el contenido (usando la función libre 'new_clone') y así permite contenedores polimórficos. También tiene una interfaz más agradable (desreferenciar el iterador produce una referencia al objeto, no una referencia al puntero del objeto) y otras cosas buenas. –

13

shared_ptr<> tiene una semántica de propietario compartido, que se implementa mediante el incremento y la disminución de los recuentos de referencia. Eso viene con un poco de sobrecarga, especialmente cuando está habilitado el multi-threading (porque esos contadores deben estar bloqueados).

Si sus objetos son compartidos, use shared_ptr<>.
Pero si son efectivamente propiedad del contenedor, y deben morir con el contenedor, y las referencias (punteros) entregadas también pueden fallar cuando el contenedor muere, luego use contenedores de puntero, ya que tienen menos sobrecarga. Si no está seguro, use shared_ptr para estar seguro. Si resulta que tienes un problema de rendimiento, siempre puedes optimizarlo más tarde. (Es más fácil optimizar un sistema en funcionamiento que obtener un sistema optimizado prematuramente).

+6

+1 for 'Es más fácil optimizar un sistema en funcionamiento y luego obtener un sistema optimizado prematuramente. – balki

+0

+1 para _" debería morir con el contenedor "_. – mskfisher

Cuestiones relacionadas