Elección entre vector::resize() y vector::reserve()

Resuelto iammilind asked hace 13 años • 4 respuestas

Estoy preasignando algo de memoria a mi vectormiembro de datos. Ejemplo:

class A {
    vector<string> t_Names;
  public:
      A () : t_Names(1000) {}
};

En algún momento, si es t_Names.size()igual a 1000, tengo la intención de aumentar el tamaño en 100. Una vez que llegue a 1100, increméntelo 100y así sucesivamente.

¿Cuál elijo entre vector::resize()y vector::reserve()? ¿Existe alguna opción mejor en este tipo de escenario?

Editar : tengo una especie de estimación precisa para el t_Names. Calculo que rondará 700los 800. Sin embargo, en determinadas (raras) situaciones, puede crecer más de 1000.

iammilind avatar Sep 13 '11 13:09 iammilind
Aceptado

¡Las dos funciones hacen cosas muy diferentes!

El resize()método (y pasar un argumento al constructor es equivalente a eso) insertará o eliminará el número apropiado de elementos en el vector para darle un tamaño determinado (tiene un segundo argumento opcional para especificar su valor). Afectará a size(), la iteración repasará todos esos elementos, push_back se insertará después de ellos y podrás acceder a ellos directamente utilizando el operator[].

El reserve()método sólo asigna memoria, pero la deja sin inicializar. Sólo afecta a capacity(), pero size()no se modificará. No hay valor para los objetos porque no se agrega nada al vector. Si luego inserta los elementos, no se producirá ninguna reasignación, porque se hizo de antemano, pero ese es el único efecto.

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

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

EDITAR 2: Edición de la pregunta del anuncio: si tiene una estimación inicial, entonces reserve()esa estimación. Si resulta que no es suficiente, deja que el vector haga su trabajo.

Jan Hudec avatar Sep 13 '2011 06:09 Jan Hudec

resize()no solo asigna memoria, sino que también crea tantas instancias como el tamaño deseado que pasa resize()como argumento. Pero reserve()sólo asigna memoria, no crea instancias. Eso es,

std::vector<int> v1;
v1.resize(1000); //allocation + instance creation
cout <<(v1.size() == 1000)<< endl;   //prints 1
cout <<(v1.capacity()==1000)<< endl; //prints 1

std::vector<int> v2;
v2.reserve(1000); //only allocation
cout <<(v2.size() == 1000)<< endl;   //prints 0
cout <<(v2.capacity()==1000)<< endl; //prints 1

Salida ( demostración en línea ):

1
1
0
1

Por lo tanto resize(), puede que no sea deseable si no desea los objetos creados por defecto. También será lento. Además, si le push_back()agrega nuevos elementos, el size()valor del vector aumentará aún más al asignarle nueva memoria (lo que también significa mover los elementos existentes al espacio de memoria recién asignado). Si lo ha utilizado reserve()al principio para asegurarse de que ya haya suficiente memoria asignada, el valor size()del vector aumentará cuando push_back()lo haga, pero no volverá a asignar nueva memoria hasta que se agote el espacio que le reservó .

Sarfaraz Nawaz avatar Sep 13 '2011 06:09 Sarfaraz Nawaz

Según su descripción, parece que desea "reservar" el espacio de almacenamiento asignado del vector t_Names.

Tenga en cuenta que resizeinicializa el vector recién asignado donde reservesolo asigna pero no construye. Por lo tanto, 'reservar' es mucho más rápido que 'redimensionar'

Puede consultar la documentación sobre la diferencia de cambio de tamaño y reserva.

dip avatar Sep 13 '2011 06:09 dip

reserve cuando no desee que los objetos se inicialicen cuando estén reservados. Además, es posible que prefiera diferenciar lógicamente y realizar un seguimiento de su recuento frente a su recuento de uso cuando cambie el tamaño. por lo tanto, hay una diferencia de comportamiento en la interfaz: el vector representará la misma cantidad de elementos cuando se reserve y será 100 elementos más grande cuando se cambie el tamaño en su escenario.

¿Existe alguna opción mejor en este tipo de escenario?

Depende completamente de sus objetivos al luchar contra el comportamiento predeterminado. algunas personas preferirán los asignadores personalizados, pero realmente necesitamos una mejor idea de qué es lo que está intentando resolver en su programa para poder asesorarlo bien.

Fwiw, muchas implementaciones de vectores simplemente duplicarán el recuento de elementos asignados cuando deban crecer. ¿Está tratando de minimizar los tamaños máximos de asignación o está tratando de reservar suficiente espacio para algún programa sin bloqueo o algo más?

justin avatar Sep 13 '2011 06:09 justin