Was ist std::pair
warum sollte ich es verwenden, und welche Vorteile boost::compressed_pair
bringen?
Antworten
Zu viele Anzeigen?compressed_pair
verwendet einige Vorlagentricks, um Platz zu sparen. In C++ kann ein Objekt (small o) nicht die gleiche Adresse wie ein anderes Objekt haben.
Selbst wenn Sie also
struct A { };
A
Größe nicht 0 sein, denn dann:
A a1;
A a2;
&a1 == &a2;
halten würde, was nicht zulässig ist.
Aber Viele Compiler führen die so genannte "Optimierung für leere Basisklassen" durch:
struct A { };
struct B { int x; };
struct C : public A { int x; };
Hier ist es gut für B
y C
die gleiche Größe zu haben, auch wenn sizeof(A)
kann nicht Null sein.
Also boost::compressed_pair
macht sich diese Optimierung zunutze und erbt, wenn möglich, von dem einen oder dem anderen Typ des Paares, wenn es leer ist.
Also ein std::pair
aussehen könnte (ich habe vieles weggelassen, Koren usw.):
template<typename FirstType, typename SecondType>
struct pair {
FirstType first;
SecondType second;
};
Das heißt, wenn entweder FirstType
o SecondType
es A
, votre pair<A, int>
muss größer sein als sizeof(int)
.
Aber wenn Sie die compressed_pair
wird der generierte Code ähnlich aussehen:
struct compressed_pair<A,int> : private A {
int second_;
A first() { return *this; }
int second() { return second_; }
};
Et compressed_pair<A,int>
ist nur so groß wie sizeof(int).
std::pair
ist ein Datentyp, der zwei Werte zu einem einzigen Objekt zusammenfasst. std::map
verwendet es für Schlüssel-Wert-Paare.
Während Sie lernen pair
können Sie sich informieren über tuple
. Es ist wie pair
sondern für die Gruppierung einer beliebigen Anzahl von Werten. tuple
ist Teil von TR1 und viele Compiler enthalten es bereits in ihren Standardbibliothek-Implementierungen.
Schauen Sie auch in Kapitel 1, "Tupel", des Buches Die Erweiterungen der C++-Standardbibliothek: Ein Tutorial und eine Referenz von Pete Becker, ISBN-13: 9780321412997, für eine ausführliche Erklärung.
Manchmal müssen Sie 2 Werte aus einer Funktion zurückgeben, und es ist oft ein Overkill, eine Klasse nur dafür zu erstellen.
std:pair ist in diesen Fällen sehr nützlich.
Ich denke, boost:compressed_pair ist in der Lage, die Mitglieder der Größe 0 wegzuoptimieren. Das ist vor allem für schwere Template-Maschinen in Bibliotheken nützlich.
Wenn Sie die Typen direkt kontrollieren, ist das irrelevant.
Es mag seltsam klingen zu hören, dass compressed_pair sich um ein paar Bytes kümmert. Aber es kann tatsächlich wichtig sein, wenn man bedenkt, wo compressed_pair verwendet werden kann. Betrachten wir zum Beispiel diesen Code:
boost::function<void(int)> f(boost::bind(&f, _1));
Die Verwendung von compressed_pair kann in Fällen wie dem obigen plötzlich große Auswirkungen haben. Was könnte passieren, wenn boost::bind den Funktionszeiger und den Platzhalter _1
als Mitglieder in sich selbst oder in einer std::pair
an sich? Nun, es könnte sich aufblähen bis zu sizeof(&f) + sizeof(_1)
. Wenn man davon ausgeht, dass ein Funktionszeiger 8 Bytes hat (nicht ungewöhnlich, vor allem bei Member-Funktionen) und der Platzhalter ein Byte hat (warum das so ist, steht in Logans Antwort), dann hätten wir 9 Bytes für das Bind-Objekt gebraucht. Wegen des Alignings könnte dies auf einem gewöhnlichen 32bit System bis zu 12 Bytes aufblähen.
boost::function
ermutigt seine Implementierungen, eine kleine Objektoptimierung anzuwenden. Das bedeutet, dass für klein Funktoren, ein kleiner Puffer, der direkt in die boost::function
Objekt wird verwendet, um den Funktor zu speichern. Für größere Funktoren müsste der Heap verwendet werden, indem der Operator new verwendet wird, um Speicher zu erhalten. Um boost Version 1.34 wurde beschlossen, folgende Maßnahmen zu ergreifen diese Optimierung weil man davon ausging, dass man einige sehr große Leistungsvorteile erzielen könnte.
Eine vernünftige (aber vielleicht immer noch recht kleine) Grenze für einen so kleinen Puffer wären 8 Byte. Das heißt, unser recht einfaches Bindungsobjekt würde no in den kleinen Puffer passen und würde die Speicherung von operator new erfordern. Würde das obige Bindungsobjekt eine compressed_pair
kann er seine Größe tatsächlich auf 8 Byte (bzw. 4 Byte bei Nichtmitglieds-Funktionszeigern) reduzieren, da der Platzhalter nichts anderes als ein leeres Objekt ist.
Was also so aussieht, als würde man für ein paar Bytes eine Menge Gedanken verschwenden, kann tatsächlich erhebliche Auswirkungen auf die Leistung haben.
- See previous answers
- Weitere Antworten anzeigen