Da es eine Vielzahl von Antworten gibt, könnten Sie verwirrt sein, aber um es zusammenzufassen:
Verwenden Sie a std::queue
. Der Grund dafür ist einfach: Es handelt sich um eine FIFO-Struktur. Sie wollen FIFO, Sie verwenden eine std::queue
.
Es macht Ihre Absicht allen anderen und sogar Ihnen selbst klar. A std::list
oder std::deque
nicht. Eine Liste kann überall eingefügt und entfernt werden, was eine FIFO-Struktur nicht tun soll, und eine Liste kann deque
an beiden Enden hinzugefügt und entfernt werden, was auch eine FIFO-Struktur nicht kann.
Deshalb sollten Sie a verwenden queue
.
Nun haben Sie nach der Leistung gefragt. Denken Sie immer an diese wichtige Faustregel: Guter Code zuerst, Leistung zuletzt.
Der Grund dafür ist einfach: Menschen, die Leistung vor Sauberkeit und Eleganz anstreben, kommen fast immer als Letzte ins Ziel. Ihr Code wird zu einem Brei, weil sie alles Gute aufgegeben haben, um wirklich nichts daraus zu machen.
Wenn Sie zuerst guten, lesbaren Code schreiben, lösen sich die meisten Ihrer Leistungsprobleme von selbst. Und wenn Sie später feststellen, dass Ihre Leistung fehlt, können Sie jetzt ganz einfach einen Profiler zu Ihrem netten, sauberen Code hinzufügen und herausfinden, wo das Problem liegt.
Das alles std::queue
ist nur ein Adapter. Es bietet die sichere Schnittstelle, verwendet jedoch innen einen anderen Container. Sie können diesen zugrunde liegenden Container auswählen, was ein hohes Maß an Flexibilität ermöglicht.
Welchen zugrunde liegenden Container sollten Sie also verwenden? Wir wissen , dass std::list
und std::deque
sowohl die notwendigen Funktionen ( push_back()
, pop_front()
, und front()
), so wie entscheiden wir?
Verstehen Sie zunächst, dass das Zuweisen (und Freigeben) von Speicher im Allgemeinen nicht schnell erledigt werden kann, da Sie zum Betriebssystem gehen und es auffordern müssen, etwas zu tun. A list
muss jedes Mal, wenn etwas hinzugefügt wird, Speicher zuweisen und ihn freigeben, wenn es verschwindet.
A deque
hingegen teilt in Stücken zu. Es wird weniger häufig als a zugewiesen list
. Stellen Sie sich das als Liste vor, aber jeder Speicherblock kann mehrere Knoten enthalten. (Natürlich würde ich vorschlagen, dass Sie wirklich lernen, wie es funktioniert .)
Allein damit deque
sollte a eine bessere Leistung erbringen, da es nicht so oft mit dem Gedächtnis zu tun hat. In Verbindung mit der Tatsache, dass Sie Daten mit konstanter Größe verarbeiten, muss diese wahrscheinlich nicht nach dem ersten Durchlauf der Daten zugeordnet werden, während eine Liste ständig zugeordnet und freigegeben wird.
Eine zweite Sache zu verstehen ist die Cache-Leistung . Das Auslagern in den Arbeitsspeicher ist langsam. Wenn die CPU dies wirklich benötigt, kann sie das Beste aus dieser Zeit herausholen, indem sie einen Teil des Arbeitsspeichers in den Cache zurücknimmt. Da eine deque
Zuweisung in Speicherblöcken erfolgt, führt der Zugriff auf ein Element in diesem Container wahrscheinlich dazu, dass die CPU auch den Rest des Containers zurückbringt. Jetzt sind alle weiteren Zugriffe auf die deque
schnell, da sich die Daten im Cache befinden.
Dies ist anders als bei einer Liste, bei der die Daten einzeln zugewiesen werden. Dies bedeutet, dass Daten über den gesamten Speicher verteilt werden können und die Cache-Leistung schlecht ist.
In Anbetracht dessen deque
sollte a eine bessere Wahl sein. Aus diesem Grund ist dies der Standardcontainer bei Verwendung von a queue
. Trotzdem ist dies immer noch nur eine (sehr) fundierte Vermutung: Sie müssen diesen Code profilieren, indem Sie deque
in einem Test und list
im anderen einen verwenden, um wirklich sicher zu sein.
Aber denken Sie daran: Lassen Sie den Code mit einer sauberen Oberfläche arbeiten, und sorgen Sie sich dann um die Leistung.
John äußert die Besorgnis, dass das Einwickeln eines list
oder deque
einen Leistungsabfall verursachen wird. Noch einmal, er oder ich können es mit Sicherheit sagen, ohne es selbst zu profilieren, aber es besteht die Möglichkeit, dass der Compiler die Aufrufe, die der queue
macht, inline macht. Das heißt, wenn Sie sagen queue.push()
, wird es wirklich nur sagen queue.container.push_back()
, den Funktionsaufruf vollständig zu überspringen.
Dies ist wiederum nur eine fundierte Vermutung, aber die Verwendung von a queue
beeinträchtigt die Leistung nicht im Vergleich zur Verwendung des zugrunde liegenden Rohcontainers. Wie ich bereits sagte, verwenden Sie das queue
, weil es sauber, einfach zu bedienen und sicher ist und wenn es wirklich zu einem Problemprofil und Test wird.