Puisqu'il existe une myriade de réponses, vous pourriez être confus, mais pour résumer:
Utilisez un std::queue
. La raison en est simple: il s'agit d'une structure FIFO. Vous voulez FIFO, vous utilisez un fichier std::queue
.
Cela rend votre intention claire à quiconque, et même à vous-même. A std::list
ou std::deque
pas. Une liste peut insérer et supprimer n'importe où, ce qui n'est pas ce qu'une structure FIFO est censée faire, et une deque
peut ajouter et supprimer de l'une ou l'autre extrémité, ce qu'une structure FIFO ne peut pas faire.
C'est pourquoi vous devez utiliser un fichier queue
.
Maintenant, vous avez posé des questions sur les performances. Tout d'abord, rappelez-vous toujours cette règle empirique importante: un bon code d'abord, les performances en dernier.
La raison en est simple: les personnes qui recherchent la performance avant la propreté et l'élégance finissent presque toujours en dernier. Leur code devient un tas de bouillie, car ils ont abandonné tout ce qui est bon pour ne rien en tirer.
En écrivant d'abord un bon code lisible, la plupart de vos problèmes de performances se résoudront d'eux-mêmes. Et si plus tard vous trouvez que vos performances font défaut, il est maintenant facile d'ajouter un profileur à votre code agréable et propre et de découvrir où se trouve le problème.
Cela dit, ce std::queue
n'est qu'un adaptateur. Il fournit l'interface sûre, mais utilise un conteneur différent à l'intérieur. Vous pouvez choisir ce conteneur sous-jacent, ce qui permet une grande flexibilité.
Alors, quel conteneur sous-jacent devriez-vous utiliser? Nous savons que std::list
et à la std::deque
fois fournir les fonctions nécessaires ( push_back()
, pop_front()
et front()
), alors comment nous décidons?
Tout d'abord, comprenez que l'allocation (et la désallocation) de la mémoire n'est pas une chose rapide à faire, en général, car cela implique d'aller au système d'exploitation et de lui demander de faire quelque chose. A list
doit allouer de la mémoire à chaque fois que quelque chose est ajouté, et la désallouer quand elle disparaît.
A deque
, d'autre part, alloue par blocs. Il allouera moins souvent qu'un fichier list
. Considérez-le comme une liste, mais chaque bloc de mémoire peut contenir plusieurs nœuds. (Bien sûr, je vous suggère d' apprendre vraiment comment cela fonctionne .)
Donc, avec cela seul, un deque
devrait mieux fonctionner, car il ne traite pas aussi souvent de la mémoire. Mélangé au fait que vous manipulez des données de taille constante, il ne sera probablement pas nécessaire d'allouer après le premier passage des données, alors qu'une liste sera constamment allouée et désallouée.
Une deuxième chose à comprendre est la performance du cache . La sortie vers la RAM est lente, donc lorsque le processeur en a vraiment besoin, il tire le meilleur parti de ce temps en ramenant une partie de la mémoire avec lui, dans le cache. Étant donné qu'une deque
allocation dans des blocs de mémoire, il est probable que l'accès à un élément de ce conteneur amènera le processeur à ramener également le reste du conteneur. Désormais, tout accès supplémentaire au deque
sera rapide, car les données sont en cache.
Cela ne ressemble pas à une liste, où les données sont allouées une par une. Cela signifie que les données peuvent être réparties partout dans la mémoire et que les performances du cache seront mauvaises.
Donc, compte tenu de cela, un deque
devrait être un meilleur choix. C'est pourquoi il s'agit du conteneur par défaut lors de l'utilisation d'un fichier queue
. Cela dit, ce n'est encore qu'une supposition (très) éclairée: vous devrez profiler ce code, en utilisant un deque
dans un test et list
dans l'autre pour vraiment le savoir avec certitude.
Mais rappelez-vous: faites fonctionner le code avec une interface propre, puis préoccupez-vous des performances.
John soulève la crainte que l'encapsulation d'un list
ou deque
entraîne une diminution des performances. Encore une fois, lui ni moi ne pouvons le dire avec certitude sans le profiler nous-mêmes, mais il y a de fortes chances que le compilateur intègre les appels qu'il queue
effectue. C'est-à-dire que lorsque vous dites queue.push()
, cela va simplement dire queue.container.push_back()
, sauter complètement l'appel de fonction.
Encore une fois, il ne s'agit que d'une supposition éclairée, mais l'utilisation de a queue
ne dégradera pas les performances par rapport à l'utilisation du conteneur sous-jacent brut. Comme je l'ai déjà dit, utilisez le queue
, car il est propre, facile à utiliser et sûr, et s'il devient vraiment un profil de problème et un test.