2010-02-02 32 views
6

Mi pregunta es simple. Cuando uso contenedores STL, ¿copian el valor que almaceno allí (usando el constructor de copias) o no? ¿Qué sucede si les doy una matriz de caracteres (char *) en lugar de una instancia de cadena? ¿Cómo se comportan? ¿Se garantiza que la información se almacenará en montón en lugar de la pila del sistema?comportamiento de los contenedores C++

Gracias por responder.

Respuesta

7

Los valores en los contenedores STL se almacenan por valor. Si usted tiene un vector de la siguiente manera:.

class BigObject 
{ 
... 
}; 

vector<BigObject> myObjs; 
myObjs.push_back(obj1); 
myObjs.push_back(obj2); 
... 

El vector hará una copia del objeto que está empujando en También en el caso de un vector, puede hacer nuevas copias más tarde cuando se tiene que reasignar la memoria subyacente, así que tenlo en cuenta.

Lo mismo ocurre cuando tiene un vector de punteros, como vector<char*>, pero la diferencia aquí es que el valor que se copia es el puntero, no la cadena a la que apunta. Por lo tanto, si tiene:

vector<char*> myStrings; 
char* str = new char[256];  // suppose str points to mem location 0x1234 here 
sprintf(str, "Hello, buffer"); 
myStrings.push_back(str); 
delete [] str; 

... el vector obtendrá una copia del puntero. El puntero que obtenga tendrá el mismo valor (0x1234), y dado que delete d ese puntero después de presionar el puntero, su vector contiene un puntero salvaje y su código eventualmente se bloqueará (más temprano que tarde, con suerte).

Lo cual, por cierto, se podría haber evitado si en lugar de utilizar char * s le cadenas utilizadas:

typedef vector<string> strings; 
strings myStrings; 
myStrings.push_back("Hello, buffer"); 
5

Copian el valor. La mayoría de los contenedores (todo?) Requieren que se definan un constructor de copia y un operador de asignación.

Si les da un char*, copian el puntero, no el valor apuntado. Entonces, será su responsabilidad asegurarse de que la cadena en sí no se destruya mientras todavía está en uso, y se destruye cuando ya no es necesaria.

+0

Para que quede claro, los contenedores copian el valor del tipo de argumento de la plantilla del elemento. Si el contenedor está definido para contener "int *", copiará los punteros a enteros, no a los enteros subyacentes. –

3

Siempre hacen copias. Si crea un vector<char *>, copiará el char* que inserta en él. Sin embargo, no copiará la cadena de caracteres a la que apunta el puntero. Si esa cadena se asignó dinámicamente, es probable que tenga una fuga, por lo que vector<string> suele ser infinitamente preferible.

1

Siempre copian cuando las pones. Si les das un puntero, copian el puntero. Los datos a los que apunta el puntero no se ven afectados. Tenga en cuenta que no se recomienda poner punteros sin procesar en contenedores STL, ya que es fácil perderlos y perder memoria. Los contenedores STL no fueron diseñados para ayudarlo con punteros crudos. Si desea utilizar punteros en contenedores STL, considere shared_ptr's from boost para envolverlos.

1

si ya recibió una serie de respuestas que señalan que cuando se pone los datos en una contenedor, se coloca allí por valor, de modo que lo que entra en el contenedor es una copia de sus datos originales.

Sin embargo, hay un tipo de excepción a esta regla: std::list tiene un miembro splice que le permite insertar una parte (o la totalidad) de una lista en otra lista. En este caso, los datos normalmente se mueven en lugar de copiarse; al menos normalmente, el empalme se realiza manipulando los punteros, de modo que los nodos que estaban en una lista se trasplantan a la otra lista.

La excepción a esto es si las dos listas usan diferentes tipos de asignador.En este caso, creo que el empalme tiene que asignar nuevos nodos, copiar datos y luego liberar los nodos antiguos. Por otra parte, este es un caso de esquina bastante oscuro: la mayoría de las personas nunca implementan sus propios tipos de asignador.

0

Además, si no desea la sobrecarga de copiar objetos enteros y no le gustan los dolores de cabeza asociados con el uso de punteros, puede usar boost :: shared_ptr dentro de un vector para asegurarse de que se liberará la memoria asignada dinámicamente solo cuando ya no se hace referencia a él.

Cuestiones relacionadas