2009-07-14 7 views
9

Im Gegensatz zu std :: map und std :: hash_map müssen die entsprechenden Versionen in Qt keine Referenz zurückgeben. Ist es nicht ziemlich ineffizient, wenn ich einen Hash für ziemlich sperrige Klasse baue?Irgendwelche Ideen, warum QHash und QMap const T anstelle von const T & amp;

EDIT

zumal es ein separates Verfahren Wert ist(), die dann durch einen Wert zurückkehren konnte.

+0

Mögliche Duplikat [Warum QMap :: operator \ [\] (const Key & key) Rückkehr nach Wert ?] (https://stackoverflow.com/questions/18503700/why-does-qmapoperatorconst-key-key-return-by-value) –

+0

@ThomasKlier sicher, nur gefragt, 5 Jahre zuvor – MadH

Antwort

29

const tiefgestellte Operatoren von STL Containern können einen Verweis auf const zurückgeben, da sie Aufrufe mit Indizes, die nicht im Container vorhanden sind, nicht verarbeiten können. Das Verhalten ist in diesem Fall nicht definiert. Folglich stellt std::map als eine kluge Entwurfsauswahl nicht einmal eine konstante Operatorüberladung im tiefgestellten Index bereit.

QMap versucht ein wenig entgegenkommender zu sein, liefert eine konstante Subscript-Operatorüberladung als syntaktischen Zucker, läuft auf das Problem mit nicht existierenden Schlüsseln, versucht wieder entgegenkommender zu sein und gibt stattdessen einen standardkonstruierten Wert zurück.

Wenn Sie die Const-Referenzkonvention von STL beibehalten möchten, müssen Sie einen statischen Wert zuweisen und einen Verweis auf ,, zurückgeben. Dies würde jedoch im Widerspruch zu den Wiedereintrittsgarantien stehen, die QMap bietet, so dass die einzige Möglichkeit darin besteht, nach Wert zurückzukehren. Die const gibt es nur Zuckerbeschichtung, um einige dumme Fehler wie constmap["foo"]++ von kompilieren zu verhindern.

Das gesagt, die Rückkehr durch Referenz ist nicht immer der effizienteste Weg. Wenn Sie einen fundamentalen Typ zurückgeben, oder mit einer aggressiveren Optimierung, wenn sizeof(T)<=sizeof(void*), gibt Return-by-Wert oft den Compiler das Ergebnis in einem Register direkt anstelle von indirekt zurück (Adresse, um in Register zu führen) oder - Himmel verboten - auf der Stapel. Der andere Grund (abgesehen von der vorzeitigen Pessimierung), das Vorübergehen-Referenzverfahren, Slicing, zu bevorzugen, gilt hier nicht, da sowohl std::map als auch QMap wertebasiert und daher homogen sind.Für einen heterogenen Container müssen Sie Zeiger halten, und Zeiger sind grundlegende Typen (mit Ausnahme von intelligenten natürlich).

Das alles gesagt, ich benutze fast nie den Const Index-Operator in Qt. Ja, es hat schönere Syntax als find() + *it, aber immer, werden Sie mit count()/ Anrufen direkt vor dem konst Index-Operator am Ende, was bedeutet, dass Sie zweimal die binäre Suche tun. Und dann Sie nicht ohnehin die winzigen Unterschiede in Rückgabewert Leistung feststellen :)

Für value() const, aber ich stimme, dass es Verweis auf const zurückkehren sollte, säumige auf den Referenz-to-Default-Wert als zweites Argument, aber ich denke, dass die Qt-Entwickler das für zu magisch hielten.

+0

"std :: map's const subscript operator ..." Aber 'std :: map' hat keinen 'const'-Subscript-Operator? –

+0

Fair genug, hat es bearbeitet. Kleinere Details, obwohl :) –

+0

"sie flat out Aufrufe mit Indizes, die nicht in den Container vorhanden sind, aber Sie können dies auf std :: map tun, das ist eine Möglichkeit, neue Werte einzufügen. Aber selbst wenn Sie im allgemeinen Fall gemeint sind, wie folgt daraus, dass sie keinen konstanten Indexoperator liefern? – CiscoIPPhone

1

Seltsam, ja.

Vielleicht ist dies wegen der gewünschten Semantik, wo z. value() für einen nicht angegebenen Schlüssel, gibt einen default-konstruierten Wert des richtigen Typs zurück. Mit Referenzen ist das nicht möglich, zumindest nicht so sauber.

Auch Dinge wie name return value optimization können die Leistung Auswirkungen dieses Entwurfs verringern.

3

Eigentlich einige der Methoden tun Rückkehr ein Hinweis ... zum Beispiel die Nicht-const-Version von operator[] eine T & zurückgibt.

Die const-Version operator[] gibt jedoch eine const T zurück. Warum? Wie "Abwickeln" bereits bemerkt hat, hat der Grund damit zu tun, was passiert, wenn der Schlüssel in der Karte nicht existiert. In der nicht-const operator[] können wir den Schlüssel der Karte hinzufügen und dann einen Verweis auf den neu hinzugefügten Eintrag zurückgeben. Die Konstante operator[] kann dies jedoch nicht, da die Karte nicht geändert werden kann. Worauf sollte es einen Hinweis geben? Die Lösung besteht darin, die Konstante operator[]const T zurückgeben und dann eine standardmäßig erstellte T für den Fall, dass der Schlüssel nicht in der Karte vorhanden ist.

+1

Ich hätte lieber Operator [] Verhalten das gleiche wie das von std :: und value() -Methode, um es nach Wert zurückzugeben ... – MadH

+0

Ok, aber warum nicht 'const T QHash :: value (const Schlüssel & Schlüssel, const T & defaultValue) const 'gibt einen Verweis zurück ? –

4

Die Dokumentation für QMap und QHash sagen ausdrücklich zu vermeiden operator[] für die Suche aus dem Grund Martin B angegeben.

Wenn Sie eine konstante Referenz möchten, verwenden Sie const_iterator find (const Key & key) const, wo Sie dann alle verwenden können:

const Key & key() const 
const T & value() const 
const T & operator*() const 
const T * operator->() const 
Verwandte Themen