c++ - example - ¿Por qué std:: vector es mucho más popular que std:: deque?
queue c++ (5)
Posible duplicado:
¿Por qué preferiría usar vector para deque
Tengo curiosidad por saber por qué std::vector
es mucho más popular que std::deque
. Deque es casi tan eficiente en la búsqueda, más eficiente en insertar (sin vector :: reserva) y permite insertar / eliminar en el frente.
Herb Sutter una vez recomendó que si quieres usar el vector, simplemente prefiera el deque (estoy parafraseando). Sin embargo, en una charla reciente sobre Writing Modern C ++ , recomienda encarecidamente pensar en std::vector
como un contenedor predeterminado. De acuerdo con el GOTW I vinculado anteriormente, incluso el estándar tiene una redacción similar.
¿Hay alguna razón para esta disparidad? ¿Es simplemente que el vector
es más simple y más conocido, o hay una razón técnica? ¿O es que ese vector
es solo un nombre más genial ...?
Además de que std::vector
es la clase de contenedor más comúnmente conocida, también tiene varias ventajas sobre std::deque
, a saber:
- Un
std::deque
típico requiere una indirección adicional para acceder a los elementos a diferencia destd::vector
. - Los iteradores en caso de
std::deque
deben ser punteros inteligentes y no punteros como en el caso destd::vector
. - Se garantiza que los elementos de un
std::vector
sean contiguos y, por lo tanto, es compatible con las funciones de estilo c que toman las matrices como parámetros. -
std::deque
no proporciona soporte para controlar la capacidad y el momento de la reasignación.
Especialmente, el último punto es notable.
La estructura de std::deque
es un poco más compleja, lo que hace que la iteración ingenua sea un poco más cara que std::vector
. Las inserciones en std::vector
con sus reasignaciones tienden a no ser un gran problema, especialmente cuando se usa reserve()
y solo se agrega al final. Además, hay reglas de invalidación más fáciles de entender para std::vector
aunque en realidad es una ventaja de std::deque
que los objetos permanezcan al insertar / eliminar solo en cada extremo (tenga en cuenta que std::deque
iterators se invalidan en cada inserción , independientemente de dónde suceda la inserción). Otra ventaja para std:vector
es la garantía de que los valores son contiguos en la memoria y provocan menos asignaciones de memoria.
Supongo que recomendaría que el uso de los algoritmos std::deque
se optimizaran consistentemente para usar secuencias segmentadas (no conozco ninguna biblioteca estándar de C ++ que haga esta optimización) y los usuarios accedían a las secuencias de forma consistente usando algoritmos (hasta donde sé , solo una pequeña fracción de usuarios considera la opción de usar algoritmos). De lo contrario, sospecharía que std::deque
es la mejor opción con respecto al rendimiento solo si aprovechas sus propiedades específicas (por ejemplo, que los objetos se quedan y que puedes insertar / eliminar al final). Sin embargo, vale la pena perfilar las dos alternativas.
La gente usa std :: vector over std :: deque por una simple razón. Se conectan con una gran cantidad de bibliotecas C y tienen functions con parámetros que requieren un puntero a un almacenamiento contiguo, que std :: deque no garantiza (no puede).
Otra razón es cuando construyes código de acuerdo con std :: deque y tus requisitos cambian para que tengas que admitir acceso contiguo, tendrás que hacer un poco de refactorización.
Me veo obligado a mencionar que existen libraries cuyos autores afirman haber creado implementaciones vectoriales más eficientes para superar las ineficiencias cuando se aumenta la capacity .
No puedo hablar por nadie más, pero puedo hacerlo por mí mismo.
Cuando leí por primera vez sobre std::deque
, pensé que era lo suficientemente bueno como para que por un tiempo lo tratara no solo como el contenedor predeterminado, sino como casi el único contenedor que utilicé.
Luego alguien preguntó por qué, y expuse largamente sobre sus virtudes y por qué era el mejor contenedor para prácticamente todo, y cómo era mucho más versátil que std::vector
.
Afortunadamente, el tipo que cuestionó mi decisión fue lo suficientemente persuasivo como para hacer algunas pruebas. Las pruebas mostraron que en casi todos los casos, std::deque
era más lento que std::vector
, a menudo por un factor sustancial (por ejemplo, alrededor de 2). De hecho, del código que había escrito usando std::deque
, el simple hecho de reemplazar std::deque
con std::vector
dio una aceleración en todos los casos excepto en un puñado.
He usado std::deque
en algunos casos desde entonces, pero definitivamente ya no lo considero el predeterminado. El simple hecho es que en la implementación habitual es notablemente más lento que std::vector
para la mayoría de los propósitos.
Debo agregar, sin embargo, que estoy razonablemente seguro de que con la implementación correcta, podría ser casi equivalente a std::vector
en prácticamente todos los casos. La mayoría usa una representación que sin duda es genial desde un punto de vista asintótico, pero que no funciona tan maravillosamente (para muchos propósitos) en el mundo real.
std::vector
se entiende muy bien, es simple y es compatible con C (tanto en términos de diseño de la memoria como en términos de utilizar punteros como iteradores).
Para algunas operaciones, también es más eficiente que std::deque
. Acceder a los elementos por índice es un ejemplo.
Para una tarea dada, tiene sentido usar el contenedor más simple que hace bien el trabajo. En muchos casos, el contenedor más simple es std::vector
.