¿Cuál es la diferencia entre un std::vector
y un std::array
en C++? ¿Cuándo se debe preferir uno a otro? ¿Cuáles son los pros y los contras de cada uno? Todo lo que hace mi libro de texto es una lista de cómo son iguales.std :: vector versus std :: array en C++
Respuesta
std::vector
es una clase de plantilla que encapsulan una matriz dinámica , almacenada en el montón, que crece y se contrae de forma automática si se añaden o eliminan elementos. Proporciona todos los enganches (begin()
, end()
, iteradores, etc.) que lo hacen funcionar bien con el resto del STL. También tiene varios métodos útiles que le permiten realizar operaciones que en una matriz normal serían engorrosas, como p. Ej. insertando elementos en el medio de un vector (maneja todo el trabajo de mover los siguientes elementos detrás de las escenas).
Dado que almacena los elementos en la memoria asignada en el montón, tiene cierta sobrecarga con respecto a las matrices estáticas.
std::array
es una clase de plantilla que encapsulan una matriz estática de tamaño, almacenada dentro del objeto en sí mismo, lo que significa que, si se instancia la clase en la pila, la matriz en sí será en la pila. Su tamaño debe conocerse en tiempo de compilación (se pasa como un parámetro de plantilla) y no puede crecer ni reducirse.
Es más limitado que std::vector
, pero a menudo es más eficiente, especialmente para tamaños pequeños, porque en la práctica es principalmente un envoltorio liviano alrededor de una matriz estilo C. Sin embargo, es más seguro, ya que la conversión implícita a puntero está deshabilitada y proporciona gran parte de la funcionalidad relacionada con STL de std::vector
y de los demás contenedores, por lo que puede usarla fácilmente con los algoritmos STL & co. De todos modos, para la misma limitación de tamaño fijo, es mucho menos flexible que std::vector
.
Para una introducción a std::array
, eche un vistazo a this article; para una introducción rápida al std::vector
y a las operaciones que son posibles en él, es posible que desee consultar su documentation.
En realidad, creo que en la norma que se describen en términos de máxima complejidad de las diferentes operaciones (por ejemplo, acceso aleatorio en un tiempo constante, iteración sobre todos los elementos en el tiempo lineal, añadir y eliminación de elementos al final en tiempo amortizado constante, etc.), pero AFAIK no hay otro método para cumplir tales requisitos además de usar una matriz dinámica.Según lo establecido por @Lucretiel, el estándar en realidad requiere que los elementos se almacenen contiguamente, por lo que es una matriz dinámica, almacenada donde lo ubica el asignador asociado.
En cuanto a su nota al pie: Si bien es cierto, el estándar también garantiza que la aritmética del puntero en los elementos internos funciona, lo que significa que tiene que ser una matriz: & vec [9] - & vec [3] == 6 es verdadero. – Lucretiel
Estoy bastante seguro de que ese vector no se contrae automáticamente, pero desde C++ 11 puede llamar a shrink_to_fit. – Dino
Estoy totalmente confundido con el término _static array_ y no estoy seguro de cuál es la terminología correcta. Quiere decir una matriz de tamaño estático y no una matriz de variable estática (una que usa almacenamiento estático). https://stackoverflow.com/questions/2672085/c-static-array-vs-dynamic-array/26466627#26466627. ¿Cuál es la terminología correcta? ¿Es static array un término descuidado para una matriz con un tamaño fijo? –
Un vector es una clase contenedor mientras que una matriz es una memoria asignada.
Su respuesta parece abordar 'std :: vector
Utilización de la clase std::vector<T>
:
... es tan rápido como utilizando matrices incorporadas, suponiendo que están haciendo solamente las cosas matrices incorporadas permiten que hagas (leer y escribir en elementos existentes).
... cambia el tamaño automáticamente cuando se insertan nuevos elementos.
... le permite insertar nuevos elementos al principio o en medio del vector, de forma automática "desplazar" el resto de los elementos de "arriba" (¿tiene sentido?). Le permite eliminar elementos en cualquier parte del
std::vector
, también, desplazando automáticamente el resto de los elementos hacia abajo.... le permite realizar una lectura verificada por rango con el método
at()
(siempre puede usar los indexadores[]
si no desea que se realice esta verificación).
Hay dos
tres principales advertencias para el uso de std::vector<T>
:
No tiene acceso fiable al puntero subyacente, que puede ser un problema si se trata de funciones de terceros que exigen la dirección de una matriz.
La clase
std::vector<bool>
es tonta. Se implementa como un bitfield condensado, no como una matriz. ¡Evítalo si quieres una matriz debool
s!Durante el uso,
std::vector<T>
s van a ser un poco más grandes que una matriz C++ con la misma cantidad de elementos. Esto se debe a que necesitan realizar un seguimiento de una pequeña cantidad de otra información, como su tamaño actual, y porque cada vez questd::vector<T>
cambian de tamaño, reservan más espacio que el que necesitan. Esto es para evitar que tengan que cambiar el tamaño cada vez que se inserta un nuevo elemento. Este comportamiento se puede cambiar proporcionando unallocator
personalizado, ¡pero nunca sentí la necesidad de hacerlo!
Editar: Después de leer la respuesta de Zud a la pregunta, me sentí que debería añadir:
La clase std::array<T>
no es lo mismo que una matriz C++. std::array<T>
es una envoltura muy delgada alrededor de las matrices de C++, con el objetivo principal de ocultar el puntero del usuario de la clase (en C++, las matrices se moldean implícitamente como punteros, a menudo con un efecto desalentador). La clase std::array<T>
también almacena su tamaño (longitud), que puede ser muy útil.
Es 'tan rápido' como usar una matriz incorporada asignada dinámicamente. Por otro lado, usar una matriz automática podría tener un rendimiento considerablemente diferente (y no solo durante la asignación, debido a los efectos de localidad). –
Para no-bool vectores en C++ 11 y posteriores, puede llamar a 'data()' en un 'std :: vector
Una de las ventajas que los vectores tienen más de matrices es que es posible encontrar la tamaño actual de un vector usando vector_name.size().
Como se puede imaginar, esto puede ser bastante útil en una variedad de situaciones, donde puede obtener fácilmente una cantidad de elementos en array_list.
También puede hacer eso con std :: array – Gerard
Para enfatizar un punto hecho por @MatteoItalia, la diferencia de eficiencia es donde se almacenan los datos. La memoria de pila (requerida con vector
) requiere una llamada al sistema para asignar memoria y esto puede ser costoso si está contando ciclos. La memoria de pila (posible para array
) es virtualmente "cero-overhead" en términos de tiempo, porque la memoria se asigna simplemente ajustando el puntero de la pila y se realiza solo una vez al ingresar a una función. La pila también evita la fragmentación de la memoria.Para estar seguro, std::array
no siempre estará en la pila; depende de dónde lo asigne, pero todavía implicará una asignación de memoria menos del montón en comparación con el vector. Si usted tiene un pequeño "matriz"
- (menos de 100 elementos dicen) - (una pila típica es de aproximadamente 8 MB, así que no se asigne más de unos pocos KB en la pila o menos si su código es recursivo)
- el tamaño será fijado
- la vida útil está en el ámbito de la función (o es un valor de miembro con el mismo tiempo de vida como la clase padre)
- ciclos usted está contando,
definitivamente el uso de una std::array
en un vector. Si alguno de esos requisitos no es cierto, utilice un std::vector
.
Buena respuesta. "Para estar seguro, std :: array no siempre estará en la pila; depende de dónde lo asigne "Entonces, ¿cómo podría crear un std :: array que no esté en la pila con una gran cantidad de elementos? – Trilarion
@Trilarion use' new std :: array' o conviértalo en miembro de una clase que usted use 'new' para asignar. –
Entonces, esto significa 'new std :: array' todavia espera conocer su tamano en tiempo de compilacion y no puede cambiar su tamano pero todavia vive en el montículo? – Trilarion
Si está considerando utilizar matrices multidimensionales, existe una diferencia adicional entre std :: array y std :: vector. Una matriz std :: multidimensional tendrá los elementos empaquetados en la memoria en todas las dimensiones, al igual que una matriz de estilo c. Un std :: vector multidimensional no se embalará en todas las dimensiones.
Dadas las siguientes declaraciones:
int cConc[3][5];
std::array<std::array<int, 5>, 3> aConc;
int **ptrConc; // initialized to [3][5] via new and destructed via delete
std::vector<std::vector<int>> vConc; // initialized to [3][5]
Un puntero al primer elemento de la matriz c-estilo (cConc) o el std :: array (aConc) se pueden repetir a través de toda la matriz mediante la adición de 1 a cada elemento precedente. Están apretados.
Un puntero al primer elemento de la matriz de vectores (vConc) o la matriz de punteros (ptrConc) solo se puede iterar a través de los primeros 5 (en este caso) elementos, y luego hay 12 bytes (en mi sistema) de sobrecarga para el siguiente vector.
Esto significa que una matriz std :: vector> inicializada como una matriz [3] [1000] será mucho más pequeña en memoria que una inicializada como una matriz [1000] [3], y ambas serán más grandes en la memoria que una matriz estándar: asignada de cualquier manera.
Esto también significa que no puede simplemente pasar una matriz multidimensional de vector (o puntero) a, por ejemplo, OpenGL sin tener en cuenta la sobrecarga de memoria, sino que puede pasar ingenuamente una matriz std :: multidimensional a OpenGL y tenerla rutina de ejercicio.
- 1. std :: vector vs normal array
- 2. C++ 11 std :: array
- 3. convert System :: array to std :: vector
- 4. C++ std :: pair, std :: vector y memcopy
- 5. Conversión entre C++ std :: vector y C array sin copiar
- 6. sizeof() std :: vector (C++)
- 7. ¿Cómo inicializar std :: vector desde C-style array?
- 8. Convertir std :: vector en matriz
- 9. Tratar C cstyle array como std :: array
- 10. ¿Por qué es diferente el comportamiento C++ initializer_list para std :: vector y std :: array?
- 11. std :: vector alternativa para C
- 12. ¿Cómo funciona C++ std :: vector?
- 13. std :: vector <std::string> crash
- 14. std :: vector de std :: vectores de contigüidad
- 15. std :: merge fusionando dos std :: vector coredump
- 16. std :: list vs std :: vector iteration
- 17. std :: vector y std :: comportamiento min
- 18. Cómo exportar std :: vector
- 19. ¿Puede un std :: vector ser = 'd a otro std :: vector?
- 20. std :: vector insert() reasignación
- 21. Puede std :: vector ser tratado como un array
- 22. Inicializando la matriz de impulso con std :: vector o array
- 23. std :: vector de funciones
- 24. Iterar std :: vector múltiple
- 25. Asignador personalizado en std :: vector
- 26. std :: array <char, N> std :: string
- 27. Boost.Python y C++ std :: vector de punteros
- 28. C++ Twodimensional std :: vector best practices
- 29. Regreso std :: vector por valor
- 30. std vector C++ - copia profunda o superficial
Estoy buscando una comparación de 'std :: vector' contra' std :: array' y cómo los términos son diferentes. – Zud
Zud, 'std :: array' no es lo mismo que una matriz C++. 'std :: array' es un contenedor muy fino alrededor de las matrices C++, con el objetivo principal de ocultar el puntero del usuario de la clase. Actualizaré mi respuesta. – ClosureCowboy
Actualicé el título y el texto de la pregunta para reflejar su aclaración. –