2010-08-13 11 views
22
vector <weight> decoy; 

void clear_decoy() { 

    decoy.clear(); 

    vector<weight> (decoy).swap(decoy); 
} 

En el método anterior clear_decoy(), ¿qué significa vector<weight> (decoy).swap(decoy);?C++ vector :: claro

¿El método es claro decoy o no? ¡Gracias!

+0

Recuerde aceptar las respuestas que considere mejores haciendo clic en la marca de verificación –

Respuesta

20

Crea un nuevo vector de Weight objetos (que estará vacío) y lo intercambia con decoy.

La razón de esto es que, de manera predeterminada, std::vector<t>::clear a menudo no reduce realmente el almacenamiento utilizado por un vector, simplemente destruye todos los objetos contenidos allí. De esta forma, el vector tiene espacio para almacenar más objetos sin reasignación en el futuro.

A veces, sin embargo, desea recortar la capacidad en el vector. El intercambio con un vector creado recientemente (que vive hasta el final de su línea, y por lo tanto se destruye allí) libera toda la memoria asignada por el vector.

+1

¡Oh querido! Mi querida C++, le ocasionas problemas a quienes te quieren siendo más inteligentes que nosotros. –

+0

Ser inteligente tiene un costo social. – Klaim

+1

Esto es muy C++ y. C++ expone la gestión de memoria aquí, por lo que tiene la posibilidad de personalizar las cosas según sus necesidades. De forma predeterminada, C++ intenta ser lo más rápido posible, por lo que si no sigue este código obtendrá un código más rápido. En los casos en que tiene un vector muy grande y elimina muchos de sus elementos, puede utilizar este modismo para liberar recursos al sistema operativo, a expensas de la velocidad. Por lo general, no desea hacer eso (es decir, no arregle lo que no está roto). – wilhelmtell

1

Con claro,

Todos los elementos del vector son Eliminado: sus destructores se llaman, y luego se retiran del recipiente vector, dejando el recipiente con un tamaño de 0.

Intercambiar simplemente intercambia los dos vectores,

Sw ap contenido

Intercambia el contenido del vector por el contenido de vec, que es otro vector del mismo tipo. Los tamaños pueden difieren.

Después de la llamada a esta función de miembro , los elementos de este contenedor son los que estaban en vec antes de la llamada, y los elementos de vec son los que estaban en este. Todos los iteradores , referencias y punteros siguen siendo válidos para los vectores intercambiados.

Parece que no está intercambiando nada realmente y simplemente restaura la asignación predeterminada. Clear puede desasignar, pero a veces no lo hace. No solo está reduciendo el tamaño, sino reduciendo el espacio asignado con la declaración de intercambio.

+0

¿se ha liberado la memoria? – ladyfafa

+0

@ladyfafa: con la declaración de intercambio, se reduce la cantidad de espacio asignado. Esa es la parte buena de los vectores. –

+0

veo, gracias !! – ladyfafa

6

clear elimina todas las entradas del vector, pero no necesariamente desasigna el espacio. Este modismo de intercambio restaura el vector a no tener espacio asignado.

+3

En realidad, 'clear' * puede * desasignar el espacio que ocupa el vector. Pero no * tiene * para. Sin embargo, generalmente no lo hace en la mayoría de las implementaciones de STL. –

+0

@Billy ONeal: Gracias. Edité mi respuesta. –

22

Nunca antes había visto esa forma.

he visto escrito como:.

vector<weight>().swap(decoy); 

que significa "crear un nuevo vector vacío, e intercambiarlo con la existente

vector<weight> (decoy).swap(decoy);

a entender que, romper en a partes

crear un nuevo vector (con sus contenidos copiados del señuelo ahora vacío). El nuevo vector es un anonomous temporal, así que pretent es su nombre es newvector.

newVector.swap(decoy); intercambia el nuevo vector con decopy.

(Actualizado por los comentarios de corrección de errores)

+3

+1 por sugerir una mejor (y más) construcción común de la misma cosa. –

+2

Tiene que ser 'vector () .swap (señuelo)'. Puede llamar a funciones miembro en temporales, pero no puede pasarlas como argumentos de referencia no constantes. –

+0

+1 Soy un mal mecanógrafo. :) –

10

que el código es un intento fallido de utilizar un truco común para garantizar la memoria asignada por el vector es liberado. Puede o no hacer eso, dependiendo de si el constructor de copia del vector asigna o no memoria para que coincida con el tamaño del otro vector, o su capacidad.

Para liberar de forma fiable la memoria, utilice la siguiente:

void clear_decoy() { 
    vector<weight>().swap(decoy); 
} 

Esto crea un vector vacío temporal (con poca o ninguna memoria asignada), intercambia esto con decoy para que la memoria es ahora propiedad de la temporal , luego destruye lo temporal, liberando la memoria.

+0

Excelente punto. –

+1

Si bien esto es cierto, ninguna implementación de STL correcta se asignará en función de la capacidad aquí. –

+0

@Billy: De hecho; Es muy probable que la torpe danza de copiado claro funcione, pero se garantiza que la versión más simple funcionará. –

3

Como 0A0D menciona, el efecto de swap es intercambiar la memoria controlada subyacente entre los dos vectores. Pero esto garantiza un poco más de explicación.

Cuando clear a vector, los elementos se eliminan de ella, al menos en lo que respecta al programador. size() se convierte en cero y capacity() puede o no puede cambiar. Pero el estándar no garantiza que la memoria utilizada por el vector realmente se devuelva al sistema operativo. Entonces, si tenía 1000 elementos en el vector antes del clear() y cada uno tomó 1000 bytes de memoria, después del clear() se llama al destructor de cada elemento, pero el vector aún puede estar reteniendo una asignación de 1,000,000 de bytes.

Esto a veces es indeseable. El 'truco de intercambio' que anota arriba tiene el efecto de intercambiar la memoria controlada entre los dos vectores. Por lo tanto, decoy termina con su reinicio de memoria controlada.

Esto es lo que sucede paso a paso:

  1. decoy elementos son cada erased. Se llama a los destructores de los elementos y el vector size() se convierte en cero. La memoria real puede no ser desasignada.
  2. Se construye un nuevo vector en la pila (vector<weight> (decoy)) y se copian los elementos de decoy. Como decoy fue solo clear() ed, no se copiaron elementos en el vector temporal. Sin embargo, mira editar a continuación. Usted no sabe que la memoria controlada no se intercambia.
  3. La memoria del vector temporal y decoy se intercambian (.swap(decoy);) dando como resultado decoy siendo ambos borrados y su memoria transferida al temporal.
  4. El temporal se cae de la pila, lo que provoca que se elimine la memoria.

Esto se conoce como "the swap trick".

EDITAR: Como Mike menciona, el programador original lo está haciendo mal. El temporal no se debe construir basado en decoy, solo debe ser construido por defecto. No está seguro de que swap() solo copie los elementos y no la memoria controlada debajo.

+0

+1 Gran explicación –