Ich habe diese Seite durchgesehen, kann aber den Grund dafür nicht ermitteln. Dort wird das erwähnt
"Es ist sinnvoller, überhaupt keinen Wert zurückzugeben und von Clients zu verlangen, dass sie front () verwenden, um den Wert an der Vorderseite der Warteschlange zu überprüfen."
Um ein Element von front () aus zu untersuchen, musste dieses Element jedoch auch in lvalue kopiert werden. Zum Beispiel in diesem Codesegment
std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);
/ * Hier wird temporär auf RHS erstellt, das dem Ergebnis zugewiesen wird. Falls Rückgaben als Referenz zurückgegeben werden, wird das Ergebnis nach der Pop-Operation ungültig. * /
result = myqueue.front(); //result.
std::cout << ' ' << result;
myqueue.pop();
In der fünften Zeile erstellt das cout- Objekt zuerst eine Kopie von myqueue.front () und weist diese dann dem Ergebnis zu. Was ist der Unterschied? Die Pop-Funktion hätte das Gleiche tun können.
void std::queue::pop();
).front()
musste dieses Element auch in lvalue kopiert werden" - nein, das tut es nicht.front
Gibt eine Referenz zurück, keinen Wert. Sie können den Wert, auf den er sich bezieht, überprüfen, ohne ihn zu kopieren.pop()
. Wenn Sie verwenden,std::queue<T, std::list<T>>
besteht keine Sorge, dass die angegebene Referenzfront()
durch a ungültig wirdpush()
. Aber Sie müssen wissen , Ihre Nutzungsmuster und Ihre Einschränkungen dokumentieren sollten.Antworten:
Es hätte tatsächlich das Gleiche tun können. Der Grund dafür ist, dass ein Pop, der das popped-Element zurückgegeben hat, bei Vorhandensein von Ausnahmen unsicher ist (er muss nach Wert zurückgegeben werden und somit eine Kopie erstellen).
Stellen Sie sich dieses Szenario vor (mit einer naiven / erfundenen Pop-Implementierung, um meinen Standpunkt zu verdeutlichen):
Wenn der Kopierkonstruktor von T bei der Rückgabe ausgelöst wird, haben Sie den Status der Warteschlange bereits geändert (
top_position
in meiner naiven Implementierung) und das Element wird aus der Warteschlange entfernt (und nicht zurückgegeben). In jeder Hinsicht (unabhängig davon, wie Sie die Ausnahme im Clientcode abfangen) geht das Element oben in der Warteschlange verloren.Diese Implementierung ist auch dann ineffizient, wenn Sie den Popup-Wert nicht benötigen (dh eine Kopie des Elements erstellt, das niemand verwenden wird).
Dies kann sicher und effizient mit zwei getrennten Operationen (
void pop
undconst T& front()
) implementiert werden .quelle
pop
? das ist ziemlich kontraintuitiv. Es könnte benannt werdendrop
, und dann ist es für alle klar, dass es das Element nichtpop
nichts zurückgegeben habe. Siehe zum Beispiel auf Wikipedia .Die Seite, auf die Sie verlinkt haben, beantwortet Ihre Frage.
Um den gesamten relevanten Abschnitt zu zitieren:
C ++ wurde unter Berücksichtigung der Effizienz über die Anzahl der Codezeilen entwickelt, die der Programmierer schreiben muss.
quelle
pop
einen Wert zurückgibt.pop kann keinen Verweis auf den Wert zurückgeben, der entfernt wird, da er aus der Datenstruktur entfernt wird. Worauf sollte sich der Verweis also beziehen? Es könnte nach Wert zurückgegeben werden, aber was ist, wenn das Ergebnis von Pop nirgendwo gespeichert wird? Dann wird Zeit damit verschwendet, den Wert unnötig zu kopieren.
quelle
pop
Rückgaben und das Zurückgeben zu einer Ausnahme führen können. Es müsste offensichtlich das Element entfernen, bevor es zurückgegeben wird, und wenn dann etwas wirft, könnte das Element unwiderruflich verloren gehen.value_type
Konstruktor einen nothrow move-Konstruktor hat, aber die Warteschlangenschnittstelle würde sich dann unterscheiden, je nachdem, welchen Objekttyp Sie darin speichern, was nicht hilfreich wäre.Mit der aktuellen Implementierung gilt dies:
Wenn Pop eine Referenz wie folgt zurückgeben würde:
Dann könnte der folgende Code abstürzen, da die Referenz nicht mehr gültig ist:
Auf der anderen Seite, wenn es einen Wert direkt zurückgeben würde:
Dann müssten Sie eine Kopie erstellen, damit dieser Code funktioniert, was weniger effizient ist:
quelle
Ab C ++ 11 wäre es möglich, das gewünschte Verhalten mithilfe der Verschiebungssemantik zu archivieren. Wie
pop_and_move
. Der Kopierkonstruktor wird also nicht aufgerufen, und die Leistung hängt nur vom Verschiebungskonstruktor ab.quelle
pop
Ausnahmen nicht auf magische Weise sicher.Sie können dies vollständig tun:
Wenn Sie den Wert in einer Variablen haben möchten, verwenden Sie eine Referenz:
Daneben: Der Wortlaut "sinnvoller" ist eine subjektive Form von "Wir haben uns mit Nutzungsmustern befasst und festgestellt, dass mehr Spaltung erforderlich ist". (Seien Sie versichert: Die C ++ - Sprache entwickelt sich nicht leicht ...)
quelle
Ich denke, die beste Lösung wäre, so etwas hinzuzufügen
Dabei erhält value den gepoppten Wert.
Der Vorteil ist, dass es mit einem Verschiebungszuweisungsoperator implementiert werden kann, während mit Front + Pop eine Kopie erstellt wird.
quelle