2011-01-11 11 views
5

puedo pensar en tres maneras de llenar un Supongamos std::vectordiferentes maneras de llenar un vector

tenemos

vector<int> v(100, 0); 

Entonces yo quiero que mantenga (1, 1, 1). Podemos hacer:

v.clear(); 
v.resize(3, 1); 

O

v = vector<int>(3, 1); 

Y aprendí otro enfoque:

vector<int>(3, 1).swap(v); 

primera pregunta es: ¿Está alguno de ellos el mejor enfoque?

Segunda pregunta: supongamos que v fue declarado fuera de la función principal. De acuerdo con esto answer, la memoria se asignará en el segmento de datos. Si utilizo el segundo o tercer enfoque, ¿se asignará la memoria a la pila?

+4

Eso no es cierto en absoluto. Las matrices primitivas asignan su memoria donde sea que estén declaradas. 'vector' siempre asignará el montón. int []! = vector. – Puppy

Respuesta

3

Así que, aquí están las diferencias y te dejaré decidir qué es lo mejor para tu situación.

v.clear(); 
v.resize(3, 1); 

En este caso, hemos marcado el vector como despejado. Todavía contiene lo que asignó para contener 100 elementos (que puede ser más que el espacio necesario para 100 elementos). Luego agregamos 3 elementos con un valor de 1. Todo esto hizo aumentar el contador de tamaño y restablecer 3 valores, la memoria subyacente sigue siendo del mismo tamaño.

v = vector<int>(3, 1); 

Esto hace más o menos lo mismo, excepto que se crea un vector adicional temporal y en lugar de que existan lugares intermitentes donde el contador es 0 y 3 con algunos valores, copia simples del tamaño mostrador y luego hace una operación similar a una memcpy para copiar sobre los 3 elementos. El tamaño de la memoria subyacente asignada para v es suficiente para contener 100 enteros.

vector<int>(3, 1).swap(v); 

Esta es significativamente diferente. En este caso, creamos un vector temporal que contiene 3 elementos que están todos inicializados en 1. Teóricamente, aún podría tener suficiente memoria reservada para 100 elementos, pero es probable que tenga mucho menos.Luego intercambiamos este vector con el nuestro y dejamos que el temporal sea destruido. Esto tiene el beneficio adicional de borrar cualquier memoria adicional asignada por nuestro vector anterior que no estaba en el temporal. La forma en que esto funciona es que los dos vectores (nuestro v y el temporal) intercambian más que solo contadores y valores, también intercambian punteros de búfer.

Esta es la única forma de reducir un vector.

+0

existe la posibilidad de que el operador de asignación también use la expresión de intercambio internamente, lo que da como resultado la misma reducción en la memoria, aunque esto no está garantizado. De hecho, no creo que pueda hacer ninguna garantía con ninguno de los 3 casos, solo establezca lo que es más probable. –

2

Para responder la segunda pregunta primero: vector siempre asignará dinámicamente la memoria para los objetos que contiene, por lo que terminará en el montón.

En cuanto a qué método de reasignación es mejor, diría que su primer o segundo método hacen que su intento sea más claro, y ese es el atributo más importante.

9

¿Qué tal si usas el miembro del vector que está ahí para esta tarea?

std::vector<int> v(100); 
v.assign(3, 1); // this is what you should do. 
+0

Qué fácil es pasar por alto lo obvio. –

+1

es una versión más corta de 'v.clear(); v.resize (3, 1); 'con el mismo problema de seguridad de excepción. –

1

El intercambio reducirá de forma efectiva el vector a 3 elementos. Los otros probablemente no.

vector<int> v(100); 
v.assign(3, 1); 
assert(v.size() == 3); 
assert(v.capacity() != 3); 

v = vector<int>(3, 1); 
// Now, v.capacity() is likely not to be 3. 

vector<int>(3, 1).swap(v); 
assert(v.capacity() == 3); 

Los otros enfoques no cambiarán el tamaño del vector internamente. Todavía ocupará 100 * sizeof (int) bytes en memoria, incluso si el miembro de size() devuelve 3. Intente mostrar v.capacity() para convencerse.

+0

Casi. No sabemos cuál será el tamaño ocupado en realidad para ninguno de estos casos. Muchas implementaciones vectoriales reservan espacio adicional para que las inserciones frecuentes no causen reasignación y movimiento individualmente. –

1

Un problema, no mencionado en publicaciones anteriores, es importante al elegir entre estas alternativas. Es decir, seguridad de excepción. El vector<int>(3, 1).swap(v); tiene una fuerte garantía de excepción de seguridad. El formulario v = vector<int>(3, 1); también podría ofrecer dicha garantía si la asignación se implementa en términos de intercambio. La primera alternativa no es segura: v.clear(); v.resize(3, 1);

Cuestiones relacionadas