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::listoder std::dequenicht. Eine Liste kann überall eingefügt und entfernt werden, was eine FIFO-Struktur nicht tun soll, und eine Liste kann dequean 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::queueist 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::listund std::dequesowohl 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 listmuss jedes Mal, wenn etwas hinzugefügt wird, Speicher zuweisen und ihn freigeben, wenn es verschwindet.
A dequehingegen 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 dequesollte 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 dequeZuweisung 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 dequeschnell, 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 dequesollte 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 dequein einem Test und listim 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 listoder dequeeinen 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 queuemacht, 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 queuebeeinträ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.