2009-09-05 10 views
12

Siempre he estado un poco confundido acerca de cómo los contenedores STL (vector, list, map ...) almacenan valores. ¿Almacenan referencias a los valores que paso, o copian/copian construir + almacenar los valores ellos mismos?STL: almacena referencias o valores?

Por ejemplo,

int i; 
vector<int> vec; 
vec.push_back(i); 
// does &(vec[0]) == &i; 

y

class abc; 
abc inst; 
vector<abc> vec; 
vec.push_back(inst); 
// does &(vec[0]) == &inst; 

Gracias

+5

Tienes lo que me parece código de trabajo que probaría la respuesta (con un pequeño cambio para hacer que el comentario sea condicional). ¡Corre y mira! Estoy bastante seguro de que copian, construyen y almacenan. –

Respuesta

18

contenedores STL copy-construir valores y almacenar las imágenes que se pasa en. Si desea almacenar objetos en un contenedor sin copiándolos, sugiero almacenar un puntero al objeto en el contenedor:

class abc; 
abc inst; 
vector<abc *> vec; 
vec.push_back(&inst); 

Esta es la forma más lógica de implementar las clases de contenedor para evitar el almacenamiento accidental de referencias a variables en marcos de pila difuntos. Considere:

class Widget { 
public: 
    void AddToVector(int i) { 
     v.push_back(i); 
    } 
private: 
    vector<int> v; 
}; 

Almacenamiento de una referencia a i sería peligroso como usted estaría haciendo referencia a la ubicación de la memoria de una variable local después de regresar del método en el que se ha definido.

+5

No puede crear contenedores de creación que almacenen referencias en C++. El argumento de tipo pasado al contenedor debe ser asignable. Las referencias no son asignables, se inicializan con un objeto pero no se pueden asignar a un objeto diferente después de la construcción. Por lo tanto, los tipos de referencia no cumplen los requisitos de tipo que se utilizarán dentro de los contenedores. Si quiere tener la misma semántica (o lo más cerca posible) debe proporcionar un contenedor de referencia (boost :: ref/boost :: cref) –

+3

@dribeas: Esta respuesta explica _por qué no_, explicando los riesgos de un hipotético implementación. – MSalters

4

Eso depende de su tipo. Si es un tipo de valor simple y barato de copiar, entonces el almacenamiento de valores es probablemente la respuesta. Por otro lado, si es un tipo de referencia, o costoso de copiar, será mejor que almacene un puntero inteligente (no auto_ptr, ya que su semántica de copia especial evita que se guarde en un contenedor. Vaya a un shared_ptr). Con un puntero simple arriesga la fuga de memoria y el acceso a la memoria liberada, mientras que con las referencias arriesga lo último. Un puntero inteligente evita ambos.

+2

+1 en el uso de punteros inteligentes dentro de contenedores para manejar la memoria. Otra opción podría ser usar una biblioteca como Boost Pointer Container para encargarse de la desasignación de recursos. –

+5

No es eso lo que el OP está preguntando. Quiere saber si las clases de contenedor copian el valor cuando se coloca en el contenedor. La respuesta es, sí, lo hacen, que es por lo que el almacenamiento de punteros puede ser bueno si el tipo particular en cuestión es caro de copiar. –

+2

Y el almacenamiento de punteros desnudos está perfectamente bien si sabe lo que está haciendo y limpia después de usted mismo. –

Cuestiones relacionadas