204 votes

Dans quel scénario dois-je utiliser un conteneur STL particulier ?

J'ai lu des articles sur les conteneurs STL dans mon livre sur le C++, en particulier la section sur la STL et ses conteneurs. Je comprends maintenant que chacun d'entre eux a ses 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 préférable.

0 votes

Voulez-vous dire map, vectot, set etc ?

0 votes

Même en regardant ce diagramme, je ne peux pas dire quelle serait la meilleure solution à utiliser dans ma question. stackoverflow.com/questions/9329011/

2 votes

@sbi : Suppression du tag C++Faq de celui-ci et ajout au tag plus récent et incluant C++11. Comment puis-je sélectionner efficacement un conteneur de la bibliothèque standard en C++11 ?

368voto

zdan Points 11822

Cet aide-mémoire fournit un assez bon résumé des différents conteneurs.

Consultez l'organigramme en bas de page pour savoir lequel utiliser dans différents scénarios d'utilisation :

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

Créé par <a href="http://linuxsoftware.co.nz/" rel="noreferrer">David Moore </a>y <a href="http://creativecommons.org/licenses/by-sa/3.0/nz/" rel="noreferrer">sous licence CC BY-SA 3.0</a>

17 votes

Cet organigramme est en or, j'aimerais avoir quelque chose comme ça en C#.

2 votes

3 votes

Le point de départ doit être vector plutôt que vide. stackoverflow.com/questions/10699265/

208voto

Mikael Persson Points 7174

Voici un organigramme inspiré de la version de David Moore (voir ci-dessus) que j'ai créée et qui est à jour (en grande partie) avec la nouvelle norme (C++11). Ce n'est que mon point de vue personnel, il n'est pas indiscutable, mais j'ai pensé qu'il pourrait être utile à cette discussion :

enter image description here

0 votes

Pouvez-vous partager un lien vers la source originale (une sorte de fichier d'organigramme) ?

0 votes

@kevinarpe Je l'ai dessiné à la main (svg). Je n'ai pas utilisé de logiciel de génération d'organigramme.

4 votes

Pouvez-vous rendre l'original disponible ? C'est un excellent tableau. Peut-être le mettre sur un blog ou sur GitHub ?

46voto

David Thornley Points 39051

Réponse simple : utiliser std::vector pour tout, sauf si vous avez une vraie raison de faire autrement.

Quand tu trouves un cas où tu te dis : "Mince alors, std::vector ne fonctionne pas bien ici à cause de X", allez-y sur la base de X.

1 votes

Cependant ... attention à ne pas supprimer / insérer des éléments lors de l'itération ... utilisez const_iterator autant que possible pour éviter cela ....

11 votes

Hmm... Je pense que les gens sur-utilisent le vecteur. La raison est que le cas "ne fonctionne pas" ne se produira pas facilement - donc les gens s'en tiennent au conteneur le plus souvent utilisé et l'utilisent à tort pour stocker des listes, des files d'attente, ... À mon avis - ce qui correspond à l'organigramme - on devrait choisir le conteneur en fonction de l'utilisation prévue au lieu d'appliquer le principe "un seul semble convenir à tous".

14 votes

Le point noir est que le vecteur est généralement plus rapide, même pour des opérations qui, en théorie, devraient être plus lentes.

11voto

Mark Krenitsky Points 186

Regardez Effective STL par Scott Meyers. Il explique bien comment utiliser la STL.

Si vous voulez stocker un nombre déterminé/indéterminé d'objets et que vous n'allez jamais en supprimer, alors un vecteur est ce qu'il vous faut. C'est le remplacement par défaut d'un tableau C, et il fonctionne comme un tableau, mais ne déborde pas. Vous pouvez également définir sa taille à l'avance avec reserve().

Si vous voulez stocker un nombre indéterminé d'objets, mais que vous allez les ajouter et les supprimer, alors vous voulez probablement une liste... parce que vous pouvez supprimer un élément sans déplacer les éléments suivants - contrairement au vecteur. En effet, vous pouvez supprimer un élément sans déplacer les éléments suivants, contrairement à un vecteur. Cependant, la liste 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 groupe d'éléments et trouver uniquement les valeurs uniques de ces éléments, vous pouvez les lire dans un ensemble et les trier pour vous.

Si vous avez beaucoup de paires clé-valeur, et que vous voulez les trier par clé, alors une map est utile... mais elle ne peut contenir qu'une seule valeur par clé. Si vous avez besoin de plus d'une valeur par clé, vous pouvez utiliser un vecteur/une liste comme valeur dans la map, ou utiliser une multimap.

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 chercher par clé, et que vous ne vous souciez pas de leur ordre, vous pourriez vouloir utiliser un hash - qui est tr1::unordered_map. Je l'ai utilisé avec Visual C++ 7.1, où il était appelé stdext::hash_map. Il a un lookup de O(1) au lieu d'un lookup de O(log n) pour map.

0 votes

J'ai entendu quelques anecdotes qui suggèrent que le système de Microsoft hash_map n'est pas une très bonne implémentation. J'espère qu'ils ont fait mieux sur unordered_map .

3 votes

De listes - "on ne peut pas accéder séquentiellement à un élément". - Je pense que tu veux dire qu'on ne peut pas accéder de façon aléatoire ou indexer directement un élément. ....

0 votes

^ Oui, parce que l'accès séquentiel est précisément ce qu'un list fait. C'est une erreur plutôt flagrante.

3voto

Bids Points 1675

Tout dépend de ce que vous voulez stocker et de ce que vous voulez faire avec le conteneur. Voici quelques exemples (très non exhaustifs) pour les classes de conteneurs que j'ai tendance à utiliser le plus :

vector : Disposition compacte avec peu ou pas de surcharge mémoire par objet contenu. Efficacité de l'itération. L'ajout, l'insertion et l'effacement peuvent être coûteux, en particulier pour les objets complexes. Bon marché pour trouver un objet contenu par index, par exemple monVecteur[10]. A utiliser là où vous auriez utilisé un tableau en C. Bon lorsque vous avez beaucoup d'objets simples (par exemple int). N'oubliez pas d'utiliser reserve() avant d'ajouter beaucoup d'objets dans le conteneur.

list : Faible surcharge de mémoire par objet contenu. Efficace pour l'itération. Append, insert et erase sont bon marché. A utiliser là où vous auriez utilisé une liste chaînée en C.

set (et multiset ) : Surcharge importante de mémoire par objet contenu. A utiliser lorsque vous avez besoin de savoir rapidement si ce conteneur contient un objet donné, ou de fusionner efficacement des conteneurs.

map (et multimap ) : Surcharge importante de mémoire par objet contenu. À utiliser lorsque vous souhaitez stocker des paires clé-valeur et rechercher rapidement des valeurs par clé.

Le diagramme de flux sur le antisèche suggéré par zdan fournit un guide plus exhaustif.

0 votes

"La liste std::list est implémentée comme une liste doublement liée et maintient donc 2 pointeurs par objet stocké, ce qui n'est pas négligeable.

0 votes

Je considère toujours que deux pointeurs par objet stocké sont "petits".

0 votes

Comparé à quoi ? std::forward_list est un conteneur qui a été principalement suggéré pour avoir moins de méta-données stockées par objet (seulement un pointeur). Alors que std::vector contient 0 méta-données par objet. Donc 2 pointeurs n'est pas négociable par rapport aux autres conteneurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X