studio programacion móviles iconfinder desarrollo curso aplicaciones c++ vector

c++ - programacion - Vector: inicialización o reserva?



manual de programacion android pdf (8)

A la larga, depende del uso y el número de elementos.

Ejecute el programa a continuación para comprender cómo el compilador reserva espacio:

vector<int> vec; for(int i=0; i<50; i++) { cout << "size=" << vec.size() << "capacity=" << vec.capacity() << endl; vec.push_back(i); }

el tamaño es el número de elementos reales y la capacidad es el tamaño real de la matriz al vector de relleno. En mi computadora, hasta 10, ambos son iguales. Pero, cuando el tamaño es 43, la capacidad es 63. Dependiendo de la cantidad de elementos, puede ser mejor. Por ejemplo, aumentar la capacidad puede ser costoso.

Sé el tamaño de un vector, ¿cuál es el mejor procedimiento para inicializarlo ?:

Opción 1

vector<int> vec(3); //in .h vec.at(0)=var1; //in .cpp vec.at(1)=var2; //in .cpp vec.at(2)=var3; //in .cpp

opcion 2

vector<int> vec; //in .h vec.reserve(3); //in .cpp vec.push_back(var1); //in .cpp vec.push_back(var2); //in .cpp vec.push_back(var3); //in .cpp

Supongo que la opción 2 es mejor que 1. ¿verdad? ¿otras opciones?


Ambas variantes tienen una semántica diferente, es decir, estás comparando manzanas y naranjas.

El primero le proporciona un vector de n valores inicializados por defecto, la segunda variante reserva la memoria, pero no los inicializa.

Elija lo que mejor se adapte a sus necesidades, es decir, qué es "mejor" en una determinada situación.


Como parece que han transcurrido 5 años y la respuesta incorrecta sigue siendo la aceptada, y la respuesta más votada es completamente inútil (se perdió el bosque por los árboles), agregaré una respuesta real.

Método n. ° 1 : pasamos un parámetro de tamaño inicial al vector (llamémoslo n .) Esto significa que el vector está lleno de n elementos, que se inicializarán a su valor predeterminado. Por ejemplo, si el vector contiene int s, lo hará estar lleno de n ceros.

Método n. ° 2 : primero creamos un vector vacío. Luego reservamos espacio para n elementos. En este caso, nunca creamos los n elementos y, por lo tanto, nunca realizamos ninguna inicialización de los elementos en el vector. Como planeamos sobrescribir los valores de cada elemento de manera inmediata, la falta de inicialización no nos hará ningún daño. Por otro lado, dado que hemos hecho menos en general, esta sería la mejor opción *.

* mejor - definición real: nunca peor . Siempre es posible que un compilador inteligente descubra lo que intenta hacer y lo optimice para usted.

Conclusión : use el método n. ° 2.


La "mejor" manera sería:

vector<int> vec = {var1, var2, var3};

disponible con un compilador capaz de C ++ 11.

No estoy seguro exactamente a qué se refiere al hacer cosas en un encabezado o archivos de implementación. Un mundo mutable es un no-no para mí. Si es un miembro de la clase, entonces se puede inicializar en la lista de inicialización del constructor.

De lo contrario, la opción 1 se usaría generalmente si sabe cuántos elementos va a utilizar y los valores predeterminados (0 para int) serían útiles.
Usar aquí significa que no puede garantizar que el índice sea válido. Una situación como esa es alarmante. A pesar de que podrá detectar problemas de manera confiable, es definitivamente más simple usar push_back y dejar de preocuparse por obtener los índices correctos.

En el caso de la opción 2, por lo general, no hay diferencia en el rendimiento si reserva memoria o no, por lo que es más sencillo no reservar *. A menos que tal vez, si el vector contiene tipos que son muy caros de copiar (y no proporcionan un movimiento rápido en C ++ 11), o el tamaño del vector va a ser enorme.

* De Stroustrups C ++ Estilo y técnica de preguntas frecuentes :

A veces las personas se preocupan por el costo de std :: vector creciendo de manera incremental. Solía ​​preocuparme por eso y usé reserve () para optimizar el crecimiento. Después de medir mi código y de tener problemas para encontrar los beneficios de rendimiento de reserve () en programas reales, dejé de usarlo, excepto cuando era necesario para evitar la invalidación del iterador (un caso raro en mi código). De nuevo: mida antes de optimizar.


La opción 2 es mejor, ya que reserva solo necesita reservar memoria (3 * sizeof (T)), mientras que la primera opción llama al constructor del tipo base para cada celda dentro del contenedor.

Para los tipos C, probablemente sea el mismo.


Otra opción es confiar en tu compilador (tm) y hacer push_back sin llamar primero a la reserve . Tiene que asignar espacio cuando comienzas a agregar elementos. Tal vez lo haga tan bien como lo haría?

Es "mejor" tener un código más simple que hace el mismo trabajo.


Si bien sus ejemplos son esencialmente los mismos, es posible que cuando el tipo utilizado no sea un int La elección se tome de usted. Si su tipo no tiene un constructor predeterminado, o si tendrá que volver a construir cada elemento más tarde de todos modos, usaría la reserve . ¡Simplemente no caiga en la trampa que hice y utilice la reserve y luego el operator[] para la inicialización!

Constructor

std::vector<MyType> myVec(numberOfElementsToStart); int size = myVec.size(); int capacity = myVec.capacity();

En este primer caso, usando el constructor, size y numberOfElementsToStart serán iguales y la capacity será mayor o igual a ellos.

Piense en myVec como un vector que contiene una serie de elementos de MyType que se puede acceder y modificar, push_back(anotherInstanceOfMyType) agregará al final del vector.

reserva

std::vector<MyType> myVec; myVec.reserve(numberOfElementsToStart); int size = myVec.size(); int capacity = myVec.capacity();

Al usar la función de reserve , el size será 0 hasta que agregue un elemento a la matriz y la capacity será igual o mayor que numberOfElementsToStart .

Piense en myVec como un vector vacío que puede tener nuevos elementos agregados utilizando push_back sin sobrecarga para al menos los primeros elementos numberOfElementsToStart .


Si ya sabes exactamente cuántos elementos contendría el vector, utiliza la opción 1. Esto eliminará la expansión innecesaria del vector a medida que agregues elementos. Aunque el tiempo amortizado para realizar la expansión es O (1), supone una diferencia de rendimiento significativa si se trata de vectores grandes o de muchos vectores en un bucle. De nuevo, es mejor evitar la optimización prematura.

La opción 2 funcionaría de manera muy similar a la opción 1 en la mayoría de los sistemas porque la mayoría de las implementaciones vectoriales reservan 0 elementos por defecto (GCC y VC ++, por ejemplo). Entonces es solo una llamada extra que estás evitando. Sin embargo, si el vector implementa n elementos de reserva por defecto (por ejemplo, el equivalente .Net del vector sí lo hace), entonces está liberando la asignación previa y luego haciendo la reasignación. Es por eso que preferiría la opción 1 en general.

La opción 2 es útil en una situación: si solo supieras aproximadamente el número de elementos que contendrá tu vector, utiliza la opción 2. En este caso, no puedes usar la opción 1, pero la opción 2 aún te da una buena idea para tu conjetura correcta. .