Warum gibt std :: queue :: pop keinen Rückgabewert zurück?

67

Ich habe diese Seite durchsucht, aber ich kann den Grund dafür nicht finden . Dort wird erwähnt, dass

  

"es ist vernünftiger, wenn es überhaupt keinen Wert zurückgibt und verlangt   Clients, die front () verwenden, um den Wert an der Vorderseite der Warteschlange zu überprüfen "

Bei der Überprüfung eines Elements von front () musste dieses Element jedoch in lvalue kopiert werden. Zum Beispiel in diesem Codesegment

%Vor%

/ * hier wird temporär auf RHS erstellt, das dem Ergebnis zugewiesen wird, und für den Fall  Wenn durch Verweis zurückgegeben wird, wird das Ergebnis nach dem Popup-Vorgang ungültig gemacht * /

%Vor%

in der fünften Zeile cout -Objekt erstellt zuerst eine Kopie von myqueue.front () und ordnet dann das Ergebnis zu. Also, was ist der Unterschied, Pop-Funktion könnte das gleiche getan haben.

    
cbinder 30.07.2014, 11:29
quelle

7 Antworten

65
  

Also, was ist der Unterschied, Pop-Funktion könnte das gleiche getan haben.

Es könnte tatsächlich das Gleiche getan haben. Der Grund dafür ist, dass ein Pop, der das Popup-Element zurückgibt, in der Gegenwart von Ausnahmen unsicher ist (muss nach Wert zurückgegeben werden und somit eine Kopie erstellen).

Betrachten Sie dieses Szenario (mit einer naiven / erfundenen Pop-Implementierung, um meinen Punkt zu verdeutlichen):

%Vor%

Wenn der Kopierkonstruktor von T bei return auslöst, haben Sie bereits den Status der Warteschlange geändert ( top_position in meiner naiven Implementierung) und das Element wird aus der Warteschlange entfernt (und nicht zurückgegeben). Für alle Absichten und Zwecke (egal wie Sie die Ausnahme im Client-Code abfangen) ist das Element am Anfang der Warteschlange verloren.

Diese Implementierung ist auch ineffizient, wenn Sie den herausgegriffenen Wert nicht benötigen (d. h. er erstellt eine Kopie des Elements, das niemand verwenden wird).

Dies kann sicher und effizient mit zwei separaten Operationen ( void pop und const T& front() ) implementiert werden.

    
utnapistim 30.07.2014, 11:42
quelle
19

Die Seite, auf die Sie verlinkt haben, beantwortet Ihre Frage.

Um den ganzen relevanten Abschnitt zu zitieren:

  

Man könnte sich fragen, warum pop () void statt value_type zurückgibt. Das heißt, warum muss man front () und pop () verwenden, um das Element am Anfang der Warteschlange zu untersuchen und zu entfernen, anstatt die beiden in einer einzigen Elementfunktion zu kombinieren? In der Tat gibt es einen guten Grund für dieses Design. Wenn pop () das Front-Element zurückgeben würde, müsste es nach Wert und nicht nach Verweis zurückgeben: Die Rückgabe als Referenz würde einen ungeeigneten Zeiger erzeugen. Die Rückgabe nach Wert ist jedoch ineffizient: Es handelt sich um mindestens einen redundanten Kopierkonstruktoraufruf. Da es unmöglich ist, dass pop () einen Wert so zurückgibt, dass es sowohl effizient als auch korrekt ist, ist es sinnvoller, überhaupt keinen Wert zurückzugeben und Clients zu veranlassen, front () zu verwenden, um den Wert zu prüfen die Vorderseite der Warteschlange.

C ++ wurde mit Blick auf die Anzahl der Codezeilen entwickelt, die der Programmierer schreiben muss.

    
BPF2010 30.07.2014 11:39
quelle
3

pop kann keinen Verweis auf den Wert zurückgeben, der entfernt wurde, da er aus der Datenstruktur entfernt wird. Worauf sollte sich die Referenz beziehen? Es könnte nach Wert zurückgegeben werden, aber was passiert, wenn das Pop-Ergebnis nicht irgendwo gespeichert wird? Dann wird Zeit verschwendet, den Wert unnötig zu kopieren.

    
Neil Kirk 30.07.2014 11:37
quelle
2

Bei der aktuellen Implementierung gilt dies:

%Vor%

Wenn Pop eine Referenz wie folgt zurückgeben würde:

%Vor%

Dann könnte der folgende Code abstürzen, da die Referenz nicht mehr gültig ist:

%Vor%

Andererseits, wenn es einen Wert direkt zurückgeben würde:

%Vor%

Dann müssten Sie eine Kopie erstellen, damit dieser Code funktioniert, was weniger effizient ist:

%Vor%     
Jan Rüegg 30.07.2014 11:38
quelle
0

Sie können das ganz machen:

%Vor%

Wenn Sie den Wert in einer Variablen haben möchten, verwenden Sie eine Referenz:

%Vor%

Außerdem: Die Formulierung "vernünftiger" ist eine subjektive Form von "wir haben Nutzungsmuster untersucht und mehr Bedarf für eine Spaltung gefunden". (Seien Sie versichert: Die C ++ - Sprache entwickelt sich nicht leichtfertig ...)

    
xtofl 30.07.2014 11:37
quelle
0

Ich denke, die beste Lösung wäre, etwas hinzuzufügen wie

%Vor%

wobei value den popping-Wert erhält.

Der Vorteil ist, dass es mit einem Verschiebezuweisungsoperator implementiert werden kann, während die Verwendung von Front + Pop eine Kopie erstellt.

    
Masse Nicolas 28.06.2016 19:27
quelle
0

Ausgehend von Cx11 wäre es möglich, das gewünschte Verhalten mit der Bewegungssemantik zu archivieren. Wie pop_and_move. Der Kopierkonstruktor wird also nicht aufgerufen, und die Leistung hängt nur vom Verschiebungskonstruktor ab.

    
Slavik Putsenko 24.01.2018 01:56
quelle

Tags und Links