J'ai lu sur les conteneurs STL dans mon livre sur C ++, en particulier la section sur la STL et ses conteneurs. Maintenant, je comprends que chacun d'entre eux a ses propres propriétés spécifiques, et je suis sur le point de les mémoriser tous ... Mais ce que je ne saisis pas encore, c'est dans quel scénario chacun d'eux est utilisé.
Quelle est l'explication? Un exemple de code est de loin préférable.
c++
stl
container-data-type
Daniel Sloof
la source
la source
Réponses:
Cette feuille de triche fournit un assez bon résumé des différents conteneurs.
Consultez l'organigramme en bas comme guide à utiliser dans différents scénarios d'utilisation:
Créé par David Moore et sous licence CC BY-SA 3.0
la source
vector
plutôt vide. stackoverflow.com/questions/10699265/…unordered_map
etunordered_set
(et leurs multiples variantes) qui ne sont pas dans l'organigramme, mais sont de bons choix lorsque vous ne vous souciez pas de la commande mais que vous avez besoin de trouver des éléments par clé. Leur recherche est généralement O (1) au lieu de O (log n).Voici un organigramme inspiré de la version de David Moore (voir ci-dessus) que j'ai créée, qui est à jour (principalement) avec le nouveau standard (C ++ 11). Ce n'est que mon point de vue personnel, ce n'est pas indiscutable, mais j'ai pensé que cela pourrait être utile pour cette discussion:
la source
vector (sorted)
c'est un peu incompatible avec le reste. Ce n'est pas un type de conteneur différent, juste le mêmestd::vector
mais trié. Plus important encore, je ne vois pas pourquoi on ne pourrait pas utiliser unestd::set
pour une itération ordonnée si c'est le comportement standard de l'itération à travers un ensemble. Bien sûr, si la réponse parle d'un accès ordonné aux valeurs de l'auge du conteneur[]
, alors ok vous ne pouvez le faire qu'avec un sotedstd::vector
. Mais dans les deux cas, la décision doit être prise juste après la question "ordre est nécessaire"Réponse simple: à utiliser
std::vector
pour tout sauf si vous avez une vraie raison de faire autrement.Lorsque vous trouvez un cas où vous pensez, "Gee,
std::vector
ne fonctionne pas bien ici à cause de X", allez sur la base de X.la source
std::remove_if
est presque toujours supérieur à l'approche "supprimer pendant l'itération".Regardez le STL efficace par Scott Meyers. C'est bon pour expliquer comment utiliser la STL.
Si vous souhaitez stocker un nombre déterminé / indéterminé d'objets et que vous n'allez jamais en supprimer, un vecteur est ce que vous voulez. C'est le remplacement par défaut d'un tableau C, et il fonctionne comme un, mais ne déborde pas. Vous pouvez également définir sa taille au préalable avec reserve ().
Si vous souhaitez stocker un nombre indéterminé d'objets, mais que vous les ajouterez et les supprimerez, vous voudrez probablement une liste ... car vous pouvez supprimer un élément sans déplacer les éléments suivants - contrairement au vecteur. Cependant, cela prend plus de mémoire qu'un vecteur et vous ne pouvez pas accéder séquentiellement à un élément.
Si vous voulez prendre un tas d'éléments et ne trouver que les valeurs uniques de ces éléments, les lire tous dans un ensemble le fera, et il les triera également pour vous.
Si vous avez beaucoup de paires clé-valeur et que vous souhaitez les trier par clé, une carte est utile ... mais elle ne contiendra qu'une seule valeur par clé. Si vous avez besoin de plus d'une valeur par clé, vous pouvez avoir un vecteur / liste comme valeur dans la carte, ou utiliser une multi-carte.
Ce n'est pas dans la STL, mais c'est dans la mise à jour TR1 de la STL: si vous avez beaucoup de paires clé-valeur que vous allez rechercher par clé, et que vous ne vous souciez pas de leur ordre, vous pourriez voulez utiliser un hachage - qui est tr1 :: unordered_map. Je l'ai utilisé avec Visual C ++ 7.1, où il s'appelait stdext :: hash_map. Il a une recherche de O (1) au lieu d'une recherche de O (log n) pour la carte.
la source
hash_map
n'est pas une très bonne implémentation. J'espère qu'ils ont fait mieuxunordered_map
.list
fait a. Erreur plutôt flagrante là-bas.J'ai repensé l'organigramme pour avoir 3 propriétés:
L'organigramme:
Plus d'informations fournies dans ce lien .
la source
Un point important que brièvement mentionné jusqu'à présent, est que si vous avez besoin de mémoire contiguë (comme un tableau C donne), alors vous ne pouvez utiliser
vector
,array
oustring
.À utiliser
array
si la taille est connue au moment de la compilation.À utiliser
string
si vous avez uniquement besoin de travailler avec des types de caractères et que vous avez besoin d'une chaîne, pas seulement d'un conteneur à usage général.Utiliser
vector
dans tous les autres cas (vector
devrait être le choix par défaut du conteneur dans la plupart des cas de toute façon).Avec ces trois éléments, vous pouvez utiliser la
data()
fonction membre pour obtenir un pointeur vers le premier élément du conteneur.la source
Tout dépend de ce que vous souhaitez stocker et de ce que vous souhaitez faire avec le conteneur. Voici quelques exemples (très non exhaustifs) des classes de conteneurs que j'ai tendance à utiliser le plus:
vector
: Disposition compacte avec peu ou pas de surcharge de mémoire par objet contenu. Efficace pour itérer. L'ajout, l'insertion et l'effacement peuvent être coûteux, en particulier pour les objets complexes. Pas cher pour trouver un objet contenu par index, par exemple myVector [10]. Utilisez là où vous auriez utilisé un tableau en C. Bon où vous avez beaucoup d'objets simples (par exemple int). N'oubliez pas d'utiliserreserve()
avant d'ajouter beaucoup d'objets au conteneur.list
: Petite surcharge de mémoire par objet contenu. Efficace pour itérer. L'ajout, l'insertion et l'effacement sont bon marché. Utilisez là où vous auriez utilisé une liste chaînée en C.set
(etmultiset
): surcharge importante de la mémoire par objet contenu. Utilisez là où vous avez besoin de savoir rapidement si ce conteneur contient un objet donné ou fusionnez des conteneurs efficacement.map
(etmultimap
): surcharge importante de la mémoire par objet contenu. Utilisez l'endroit où vous souhaitez stocker les paires clé-valeur et recherchez rapidement les valeurs par clé.L'organigramme sur la feuille de triche suggérée par zdan fournit un guide plus exhaustif.
la source
Une leçon que j'ai apprise est la suivante: essayez de l'envelopper dans une classe, car changer le type de conteneur un beau jour peut donner de grandes surprises.
Cela ne coûte pas cher au départ et permet de gagner du temps lors du débogage lorsque vous souhaitez interrompre chaque fois que quelqu'un effectue l'opération x sur cette structure.
En venant à sélectionner la structure de données parfaite pour un travail:
Chaque structure de données fournit certaines opérations, qui peuvent être de complexité temporelle variable:
O (1), O (lg N), O (N), etc.
Vous devez essentiellement deviner au mieux quelles opérations seront les plus effectuées et utiliser une structure de données qui a cette opération comme O (1).
Simple, n'est-ce pas (-:
la source
auto myIterator = whateverCollection.begin(); // <-- immune to changes of container type
typedef Collection<Foo*> CollectionOfFoo;
ce suffisant?J'ai développé le fantastique organigramme de Mikael Persson . J'ai ajouté quelques catégories de conteneurs, le conteneur de tableau et quelques notes. Si vous souhaitez votre propre copie, voici le dessin Google. Merci, Mikael d'avoir fait le travail de base! Sélecteur de conteneurs C ++
la source
J'ai répondu à cela dans une autre question qui est marquée comme dupe de celle-ci. Mais je pense qu'il est agréable de se référer à quelques bons articles concernant la décision de choisir un conteneur standard.
Comme @David Thornley a répondu, std :: vector est la voie à suivre s'il n'y a pas d'autres besoins spéciaux. C'est le conseil donné par la créatrice de C ++, Bjarne Stroustrup dans un blog de 2014.
Voici le lien de l'article https://isocpp.org/blog/2014/06/stroustrup-lists
et citer celui-là,
Dans les commentaires, l'utilisateur @NathanOliver fournit également un autre bon blog, qui a des mesures plus concrètes. https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html .
la source