Hay un hilo en la sección de comentarios de este post sobre el uso std::vector::reserve()
vs 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 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? ¿VS2010 SP1 es correcto o está mal?
resize()
y se despejó la duda. Para los moderadores: no duden en eliminar esta pregunta si está "demasiado localizada" o conservarla si creen que podría ayudar a otra persona en el futuro.Respuestas:
Hay dos métodos diferentes por una razón:
std::vector::reserve
asignará la memoria, pero no cambiará el tamaño de su vector, que tendrá un tamaño lógico igual que antes.std::vector::resize
realmente modificará el tamaño de su vector y llenará cualquier espacio con objetos en su estado predeterminado. Si son enteros, todos serán cero.Después de reservar, en su caso, necesitará muchos push_backs para escribir en el elemento 5. Si no desea hacer eso, entonces en su caso debería usar resize.
Una cosa sobre la reserva: si luego agrega elementos con push_back, hasta que alcance la capacidad que ha reservado, las referencias, iteradores o punteros existentes a los datos en su vector seguirán siendo válidos. Entonces, si reservo 1000 y mi tamaño es 5,
&vec[4]
seguirá siendo el mismo hasta que el vector tenga 1000 elementos. Después de eso, puedo llamarpush_back()
y funcionará, pero es posible que el puntero almacenado de&vec[4]
antes ya no sea válido.fuente
std::vector::reserve
Evitará la copia ocasional de la matriz completapush_back
?< size()
No se permite la indexación en elementos que no existen dentro del contenedor. No existen allí, según la definición del idioma. Si su compilador decide no lanzar las armas nucleares y en lugar de eso, solo empuja / asoma la RAM de la manera que usted quiere, es buena suerte. O mala suerte, supongo; idealmente podríamos detectar todas las cosas inválidas que harían todos los programadores, pero ¡ buena suerte para llegar allí!Respondido aquí por Jan Hudec : Elección entre vector :: resize () y vector :: reserve ()
fuente
Depende de lo que quieras hacer.
reserve
no no añadir ningún elemento a lavector
; solo cambia elcapacity()
, lo que garantiza que la adición de elementos no se reasignará (y, por ejemplo, invalidará los iteradores).resize
agrega elementos inmediatamente. Si desea agregar elementos más tarde (insert()
,push_back()
), usereserve
. Si desea acceder a los elementos más tarde (usando[]
oat()
), useresize
. EntoncesMyClass::my_method
puedes 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 eligió es una cuestión de gusto, pero el código que cita es claramente incorrecto.
fuente
Probablemente debería haber una discusión sobre cuándo se llaman a ambos métodos con un número MENOR que el tamaño actual del vector.
Llamar
reserve()
con un número menor que la capacidad no afectará el tamaño ni la capacidad.Llamando
resize()
con un número menor que el tamaño actual, el contenedor se reducirá a ese tamaño destruyendo efectivamente el exceso de elementos.En resumen
resize()
, liberará memoria mientrasreserve()
que no.fuente
Sí, tienes razón, Luchian acaba de cometer un error tipográfico y probablemente esté demasiado privado de café para darse cuenta de su error.
fuente
redimensionar en realidad cambia la cantidad de elementos en el vector, los nuevos elementos se construyen por defecto si el redimensionamiento 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 al tamaño especificado, pero no cambia el "tamaño" de la matriz, solo se 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 un int eso no es tan malo, pero en el caso de un vector de clases estaría accediendo a objetos que no han sido construidos.
La comprobación de límites de compiladores configurados en modo de depuración obviamente puede confundirse con este comportamiento, que puede ser la razón por la que está experimentando el bloqueo.
fuente