2010-04-23 12 views
8

Me gustaría 'encoger para ajustar' un std::vector, para reducir su capacidad a su tamaño exacto, de modo que se libere memoria adicional. El truco estándar parece ser el que se describe here:¿Cómo encoger y ajustar un std :: vector de una manera eficiente con la memoria?

template< typename T, class Allocator > 
void shrink_capacity(std::vector<T,Allocator>& v) 
{ 
    std::vector<T,Allocator>(v.begin(),v.end()).swap(v); 
} 

El punto entero de contracción para el montaje es para ahorrar memoria, pero no este método primero crear una copia profunda y luego intercambia los casos? Entonces, en algún momento, cuando se construye la copia, ¿el uso de la memoria se duplica?

Si ese es el caso, ¿hay un método más fácil de ajustar la memoria para reducir el tamaño? (En mi caso, el vector es muy grande y no puedo permitirme tener tanto el original como una copia en memoria en cualquier momento.)

+0

¿Duplicado ?: http://stackoverflow.com/questions/1111078/reduce-the-capacity-of-an-stl-vector – ergosys

+2

En realidad, no quiere evitar la copia temporal de ambos elementos en la memoria al mismo tiempo mientras se produce el intercambio. –

+0

En realidad, de eso se trata la otra pregunta (evitar la copia). Gracias por el enlace. – Frank

Respuesta

3

Bueno, si quisieras cambiar el tamaño de una matriz, ¿qué harías? Tienes que crear uno nuevo y copiar todos los valores, ya sea individualmente o con memcpy o lo que sea. Realmente no se puede cambiar el tamaño de una matriz en C o C++.

std::vector está prácticamente garantizado que se implementará utilizando una matriz para su almacenamiento (IIRC, el estándar no garantiza que sea una matriz, pero una matriz es la única que puede cumplir los diversos requisitos de la API, como por ejemplo cada operación debe ser eficiente, por lo que, en efecto, está garantizada incluso si esa garantía no es explícita). Como se implementó utilizando una matriz, y no puede redimensionar las matrices sin copiar, no puede cambiar el tamaño de los vectores sin copiar.

Se podría, en teoría, tener una función shrink_capacity() que ocultaba el hecho de que tenía más o menos el doble de sus requisitos de tamaño, pero desde std::vector no tiene actualmente temporalmente una función de este tipo, lo que tiene que hacer realmente una copia explícita . El truco de intercambio es solo una buena forma de hacerlo.

Si realmente le importa la memoria en ese caso, lo que puede hacer es usar punteros (o punteros inteligentes) en lugar de hacer que el vector mantenga los objetos directamente. Eso puede no ser del todo deseable, pero reduciría sus requisitos de memoria.

+0

¿Por qué no puede stl :: Vector simplemente le dice a malloc (o nuevo) que ya no necesita la memoria de la entrada final al tamaño reservado? Luego, el asignador de montones puede ponerlo de nuevo en la lista libre; no es necesario copiar nada –

+1

@Martin Nunca he oído hablar de ninguna forma de hacerlo.Hay un realloc, pero como eso no tiene ninguna garantía de que devolverá el mismo bloque de memoria, perderá todo lo que había en el conjunto. Si hay una manera de hacerlo, supongo que el vector podría hacer eso, pero actualmente no tiene esa función, incluso si es posible. –

+5

Porque la mayoría de los asignadores de memoria no funcionan de esa manera; no puede editar la etiqueta de límite de un bloque ya asignado para hacerlo más pequeño en su lugar mientras cede la holgura a la lista libre. Algunos asignadores exóticos pueden hacer esto, pero la biblioteca estándar no está diseñada para depender de ellos. – Crashworks

-1

Si su nuevo tamaño es la mitad del original, puede escaparse colocando su nuevo vector (o una matriz Dynaimc recta si el vector no puede hacer esto) en la parte final no utilizada de la anterior . No estoy seguro de si el vector almacena información en esa área de la memoria, por lo que sería muy raro y aterrador. Pero es una idea.

Ahora que lo pienso, una operación de tipo memMove() donde copie la información en reversa desde el último índice usado en el original hasta la parte posterior del área no utilizada en el original preservaría los datos. Si ha hecho esto una ubicación nueva de una matriz, podría apuntarla a donde hubiera existido la nueva información en el medio en el área de memoria original. Un movimiento in situ per se.

Cuestiones relacionadas