¿En qué escenario uso un contenedor STL en particular?

10 minutos de lectura

¿En que escenario uso un contenedor STL en particular
daniel sloof

He estado leyendo sobre contenedores STL en mi libro sobre C++, específicamente la sección sobre STL y sus contenedores. Ahora entiendo que todos y cada uno de ellos tienen sus propias propiedades específicas, y estoy cerca de memorizarlos todos… Pero lo que aún no entiendo es en qué escenario se usa cada uno de ellos.

¿Cuál es la explicación? Se prefiere mucho el código de ejemplo.

  • ¿Te refieres a mapa, vectot, conjunto, etc.?

    – Thomas Tempelman

    23 de enero de 2009 a las 0:35

  • Incluso mirando este diagrama, no puedo decir cuál sería el mejor para usar en mi pregunta stackoverflow.com/questions/9329011/…

    – sergiol

    24 de febrero de 2012 a las 19:32

  • he creado un Versión editable de la hoja de referencia del contenedor C++ de Mikael. Esta es la hoja de trucos de @MikaelPersson. Lamentablemente, no puedo comentar sobre su respuesta porque aún no tengo 50 reputación.

    –Parker Shamblin

    14 de agosto de 2020 a las 19:53

1647538992 789 ¿En que escenario uso un contenedor STL en particular
zdan

esta hoja de trucos proporciona un resumen bastante bueno de los diferentes contenedores.

Consulte el diagrama de flujo en la parte inferior como una guía para usar en diferentes escenarios de uso:

http://linuxsoftware.co.nz/containerchoice.png

Creado por david moore y con licencia CC BY-SA 3.0

  • Este diagrama de flujo es oro, desearía tener algo así en C#

    – Bruno

    1 de febrero de 2013 a las 15:35

  • Enlace actualizado: Hoja de referencia de contenedores de C++.

    – Bill puerta

    2 de enero de 2014 a las 22:56

  • El punto de partida debe ser vector en lugar de vacío. stackoverflow.com/questions/10699265/…

    – eonil

    18/02/2014 a las 19:34


  • Ahora tienes unordered_map y unordered_set (y sus múltiples variantes) que no están en el diagrama de flujo pero son buenas elecciones cuando no le importa el orden pero necesita encontrar elementos por clave. Su búsqueda suele ser O(1) en lugar de O(log n).

    – Aidiakapi

    12 mayo 2014 a las 18:38


  • @shuttle87 no solo ese tamaño nunca variará, sino que lo más importante es que el tamaño se determina en el momento de la compilación y nunca variará.

    – YoungJohn

    24/07/2015 a las 20:51


Aquí hay un diagrama de flujo inspirado en la versión de David Moore (ver arriba) que creé, que está actualizado (en su mayoría) con el nuevo estándar (C++ 11). Esta es solo mi opinión personal, no es indiscutible, pero pensé que podría ser valiosa para esta discusión:

ingrese la descripción de la imagen aquí

  • ¿Puedes hacer que el original esté disponible? Es un gráfico excelente. ¿Quizás pegarse en un blog o GitHub?

    – Kevinarpe

    2 de mayo de 2015 a las 13:28

  • Este es un gráfico excelente. Aunque, ¿alguien puede explicarme qué significa ‘posiciones persistentes’?

    – IDDQD

    26 de abril de 2016 a las 15:52

  • @STALKER Las posiciones persistentes significan que si tiene un puntero o iterador a un elemento en el contenedor, ese puntero o iterador seguirá siendo válido (y apuntará al mismo elemento) independientemente de lo que agregue o elimine del contenedor (siempre que no es el elemento en cuestión).

    – Mikael Personson

    29 de abril de 2016 a las 4:22

  • Este es realmente un gran gráfico, sin embargo, creo que vector (sorted) es un poco inconsistente con el resto. No es otro tipo de contenedor, simplemente el mismo std::vector pero ordenado. Aún más importante, no veo por qué uno no podría usar un std::set para la iteración ordenada si ese es el comportamiento estándar de iterar a través de un conjunto. Claro, si la respuesta habla de acceder ordenadamente a los valores del contenedor a través []entonces solo puedes hacer eso con un soted std::vector. Pero en cualquier caso, la decisión debe tomarse justo después de la pregunta “se necesita orden”.

    – RA

    14/10/2016 a las 20:27

  • @ user2019840 Quería restringir el gráfico a contenedores estándar. Lo que debería aparecer en lugar de “vector ordenado” es “flat_set” (de Boost.Contenedor), o equivalente (cada biblioteca principal o base de código tiene un equivalente flat_set, AFAIK). Pero estos no son estándar y son una omisión bastante evidente del STL. Y la razón por la que no desea iterar a través de std::set o std::map (al menos no con frecuencia) es que es muy ineficiente para hacerlo.

    – Mikael Personson

    27 de noviembre de 2016 a las 7:38

1647538994 304 ¿En que escenario uso un contenedor STL en particular
david thornley

Respuesta simple: usar std::vector para todo a menos que tenga una razón real para hacer lo contrario.

Cuando encuentre un caso en el que esté pensando: “Caramba, std::vector no funciona bien aquí debido a X”, vaya sobre la base de X.

  • Sin embargo… tenga cuidado de no eliminar/insertar elementos al iterar… use const_iterator en la medida de lo posible para evitar esto…

    – vrdhn

    20 de marzo de 2012 a las 16:13

  • Hmm… Creo que la gente está usando demasiado el vector. La razón es que el caso “no funciona” no sucederá fácilmente, por lo que las personas se apegan al contenedor que se usa con más frecuencia y lo usan incorrectamente para almacenar listas, colas, … En mi opinión, que coincide con el diagrama de flujo, uno debe elegir el contenedor en función del uso previsto en lugar de aplicar el “parece que sirve para todos”.

    – Negro

    13 abr 2012 a las 13:50

  • @Black Point es que el vector suele ser más rápido incluso en operaciones que, en teoría, deberían funcionar más lentamente.

    –Bartek Banachewicz

    7 febrero 2013 a las 0:30

  • @Vardhan std::remove_if es casi siempre superior al enfoque de “eliminación durante la iteración”.

    – fredo desbordamiento

    29 de abril de 2014 a las 6:35

  • Algunos puntos de referencia realmente ayudarían a que esta discusión sea menos subjetiva.

    – Félix D.

    8 de diciembre de 2019 a las 13:02

Mira Eficaz STL de Scott Meyers. Es bueno para explicar cómo usar el STL.

Si desea almacenar un número determinado/indeterminado de objetos y nunca va a eliminar ninguno, entonces lo que desea es un vector. Es el reemplazo predeterminado de una matriz C y funciona como tal, pero no se desborda. También puede establecer su tamaño de antemano con reserve().

Si desea almacenar una cantidad indeterminada de objetos, pero los agregará y los eliminará, entonces probablemente desee una lista… porque puede eliminar un elemento sin mover los siguientes elementos, a diferencia del vector. Sin embargo, requiere más memoria que un vector y no puede acceder secuencialmente a un elemento.

Si desea tomar un montón de elementos y encontrar solo los valores únicos de esos elementos, leerlos todos en un conjunto lo hará, y también los clasificará por usted.

Si tiene muchos pares clave-valor y desea ordenarlos por clave, entonces un mapa es útil… pero solo tendrá un valor por clave. Si necesita más de un valor por clave, puede tener un vector/lista como su valor en el mapa o usar un mapa múltiple.

No está en la STL, pero sí en la actualización TR1 de la STL: si tiene muchos pares clave-valor que va a buscar por clave y no le importa su orden, puede quiere usar un hash, que es tr1::unordered_map. Lo he usado con Visual C++ 7.1, donde se llamaba stdext::hash_map. Tiene una búsqueda de O(1) en lugar de una búsqueda de O(log n) para el mapa.

1647538994 29 ¿En que escenario uso un contenedor STL en particular
Ebrahim

Rediseñé el diagrama de flujo para que tuviera 3 propiedades:

  1. Creo que los contenedores STL se dividen en 2 clases principales. Los contenedores básicos y aquellos aprovechan los contenedores básicos para implementar una política.
  2. Al principio, el diagrama de flujo debe dividir el proceso de decisión en las situaciones principales sobre las que debemos decidir y luego elaborar cada caso.
  3. Algunos contenedores ampliados tienen la posibilidad de elegir diferentes contenedores básicos como su contenedor interior. El diagrama de flujo debe considerar las situaciones en las que se puede utilizar cada uno de los contenedores básicos.

El diagrama de flujo: ingrese la descripción de la imagen aquí

Más información proporcionada en este enlace.

  • Hmmm, creo que tu std::array debiera ser std::unique_ptr<T[]>. Sumario rápido: vector tiene tamaño variable, unique_ptr<T[]> tiene un tamaño determinado en el momento de la creación, array requiere que su tamaño sea una constante de tiempo de compilación.

    – Ben Voigt

    14 de agosto de 2020 a las 21:04

1647538995 726 ¿En que escenario uso un contenedor STL en particular
Pedro Mortensen

Un punto importante que solo se mencionó brevemente hasta ahora es que si necesita memoria contigua (como la que proporciona una matriz C), entonces solo puede usar vector, arrayo string.

Utilizar array si el tamaño se conoce en tiempo de compilación.

Utilizar string si solo necesita trabajar con tipos de caracteres y necesita una cadena, no solo un contenedor de propósito general.

Utilizar vector en todos los demás casos (vector debería ser la opción predeterminada de contenedor en la mayoría de los casos de todos modos).

Con los tres de estos se puede utilizar el data() función miembro para obtener un puntero al primer elemento del contenedor.

  • Hmmm, creo que tu std::array debiera ser std::unique_ptr<T[]>. Sumario rápido: vector tiene tamaño variable, unique_ptr<T[]> tiene un tamaño determinado en el momento de la creación, array requiere que su tamaño sea una constante de tiempo de compilación.

    – Ben Voigt

    14 de agosto de 2020 a las 21:04

¿En que escenario uso un contenedor STL en particular
Ofertas

Todo depende de lo que quieras almacenar y lo que quieras hacer con el contenedor. Aquí hay algunos ejemplos (muy no exhaustivos) de las clases de contenedor que tiendo a usar más:

vector: diseño compacto con poca o ninguna sobrecarga de memoria por objeto contenido. Eficiente para iterar. Agregar, insertar y borrar puede ser costoso, especialmente para objetos complejos. Barato para encontrar un objeto contenido por índice, por ejemplo, myVector[10]. Úselo donde hubiera usado una matriz en C. Bueno, donde tiene muchos objetos simples (por ejemplo, int). No olvides usar reserve() antes de agregar muchos objetos al contenedor.

list: pequeña sobrecarga de memoria por objeto contenido. Eficiente para iterar. Agregar, insertar y borrar son baratos. Use donde hubiera usado una lista enlazada en C.

set (y multiset): sobrecarga de memoria significativa por objeto contenido. Úselo donde necesite averiguar rápidamente si ese contenedor contiene un objeto determinado, o combine contenedores de manera eficiente.

map (y multimap): sobrecarga de memoria significativa por objeto contenido. Úselo donde desee almacenar pares clave-valor y busque valores por clave rápidamente.

El diagrama de flujo en el hoja de trucos sugerido por zdan proporciona una guía más exhaustiva.

  • “Pequeña sobrecarga de memoria por objeto contenido” no es cierto para la lista. std::list se implementa como una lista doblemente enlazada y, por lo tanto, mantiene 2 punteros por objeto almacenado que no debe descuidarse.

    – Hanna Khalil

    16 de noviembre de 2016 a las 11:33

  • Todavía contaría dos punteros por objeto almacenado como “pequeños”.

    – Ofertas

    16 de noviembre de 2016 a las 16:18

  • ¿comparado con que? std::forward_list es un contenedor que se sugirió principalmente para tener menos metadatos almacenados por objeto (solo un puntero). Mientras que std::vector contiene 0 metadatos por objeto. Entonces 2 punteros no es negociable en comparación con otros contenedores

    – Hanna Khalil

    17/11/2016 a las 20:38

  • Todo depende del tamaño de tus objetos. Ya dije que el vector tiene un “diseño compacto con poca o ninguna sobrecarga de memoria por objeto contenido”. Todavía diría que list tiene una sobrecarga de memoria pequeña en comparación con set y map, y una sobrecarga de memoria ligeramente mayor que vector. ¡No estoy muy seguro de qué punto estás tratando de hacer TBH!

    – Ofertas

    18 de noviembre de 2016 a las 12:44


  • Todos los contenedores basados ​​en modo tienden a tener una sobrecarga significativa debido a la asignación dinámica, que rara vez es gratuita. A menos, por supuesto, que esté utilizando un asignador personalizado.

    – Mike MB

    27 de agosto de 2017 a las 5:52

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad