vectors example cplusplus c++ stl vector

c++ - example - std:: vector:: resize() contra std:: vector:: reserve()



vector c++ (6)

Hay un hilo en la sección de comentarios en esta publicación sobre el uso de std::vector::reserve() contra std::vector::resize() .

Aquí está el código original:

void MyClass::my_method() { my_member.reserve(n_dim); for(int k = 0 ; k < n_dim ; k++ ) my_member[k] = k ; }

Creo que para escribir elementos en el vector , lo correcto es llamar a std::vector::resize() , no std::vector::reserve() .

De hecho, el siguiente código de prueba "falla" en las compilaciones de depuración en VS2010 SP1:

#include <vector> using namespace std; int main() { vector<int> v; v.reserve(10); v[5] = 2; return 0; }

¿Estoy en lo cierto o estoy equivocado? ¿Y es VS2010 SP1 correcto, o es incorrecto?


Depende de lo que quieras hacer. reserve no agrega ningún elemento al vector ; solo cambia la capacity() , lo que garantiza que la adición de elementos no reasignará (y por ejemplo invalidará los iteradores). resize agrega elementos de inmediato. Si desea agregar elementos más adelante ( insert() , push_back() ), use reserve . Si desea acceder a los elementos más tarde (usando [] o at() ), use resize . Así que eres MyClass::my_method puede ser:

void MyClass::my_method() { my_member.clear(); my_member.reserve( n_dim ); for ( int k = 0; k < n_dim; ++ k ) { my_member.push_back( k ); } }

o

void MyClass::my_method() { my_member.resize( n_dim ); for ( int k = 0; k < n_dim; ++ k ) { my_member[k] = k; } }

Cuál elegiste es una cuestión de gusto, pero el código que citas es claramente incorrecto.


Hay dos métodos diferentes por una razón:

std::vector::reserve asignará la memoria pero no redimensionará su vector, que tendrá un tamaño lógico igual al anterior.

std::vector::resize realmente modificará el tamaño de su vector y rellenará cualquier espacio con objetos en su estado predeterminado. Si son enteros, todos serán cero.

Después de la reserva, en su caso, necesitará una gran cantidad de push_backs para escribir en el elemento 5. Si no desea hacer eso, entonces en su caso debe usar el tamaño.


Probablemente debería haber una discusión sobre cuándo se invocan ambos métodos con un número que es MENOS que el tamaño actual del vector.

Llamar a reserve() con un número menor que la capacidad no afectará el tamaño o la capacidad.

Llamando a resize() con un número más pequeño que el tamaño actual, el contenedor se reducirá a ese tamaño destruyendo efectivamente los elementos en exceso.

Para resumir, resize() liberará memoria mientras que reserve() no lo hará.


Respondido aquí por Jan Hudec : Elección entre vector :: resize () y vector :: reserve ()

Las dos funciones hacen cosas muy diferentes.

El método resize () (y el argumento que pasa al constructor es equivalente a eso) insertará una cantidad determinada de elementos en el vector (tiene un segundo argumento opcional para especificar su valor). Afectará el tamaño (), la iteración recorrerá todos esos elementos, push_back se insertará después de ellos y podrá acceder directamente a ellos utilizando el operador [].

El método reserve () solo asigna memoria, pero la deja sin inicializar. Solo afecta la capacidad (), pero el tamaño () no cambiará. No hay ningún valor para los objetos, porque no se agrega nada al vector. Si luego inserta los elementos, no se realizará ninguna reasignación, ya que se realizó por adelantado, pero ese es el único efecto.

Entonces depende de lo que quieras. Si desea una matriz de 1000 elementos predeterminados, use resize (). Si desea una matriz a la que espera insertar 1000 elementos y desea evitar un par de asignaciones, use reserve ().

EDITAR: El comentario de Blastfurnace me hizo leer la pregunta nuevamente y darse cuenta de que, en su caso, la respuesta correcta es no preasignar manualmente. Solo sigue insertando los elementos al final según lo necesites. El vector se reasignará automáticamente según sea necesario y lo hará de manera más eficiente que la manera manual mencionada. El único caso donde reserve () tiene sentido es cuando tiene una estimación razonablemente precisa del tamaño total que necesitará fácilmente disponible con anticipación.

EDIT2: edición de pregunta publicitaria: si tiene una estimación inicial, que reserve () esa estimación y si resulta que no es suficiente, simplemente deje que el vector lo haga.


Sí, estás en lo cierto, Luchian acaba de hacer un error tipográfico y probablemente esté demasiado privado de café para darse cuenta de su error.


cambiar el tamaño realmente cambia la cantidad de elementos en el vector, los nuevos elementos se construyen por defecto si el cambio de tamaño hace que el vector crezca.

vector<int> v; v.resize(10); auto size = v.size();

en este caso, el tamaño es 10.

reserve, por otro lado, solo solicita que el búfer interno crezca hasta el tamaño especificado, pero no cambia el "tamaño" de la matriz, solo cambia el tamaño del búfer.

vector<int> v; v.reserve(10); auto size = v.size();

en este caso, el tamaño sigue siendo 0.

Entonces, para responder a su pregunta, sí tiene razón, incluso si reserva suficiente espacio, todavía está accediendo a la memoria no inicializada con el operador de índice. Con int no es tan malo, pero en el caso de un vector de clases estarías accediendo a objetos que no han sido construidos.

La verificación de límites de los compiladores configurados en modo de depuración obviamente puede confundirse con este comportamiento, que puede ser el motivo por el que está experimentando el bloqueo.