46 Stimmen

Was ist std::pair?

Was ist std::pair warum sollte ich es verwenden, und welche Vorteile boost::compressed_pair bringen?

81voto

Logan Capaldo Punkte 38523

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).

35voto

jwfearn Punkte 27520

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.

alt text

12voto

David Pierre Punkte 9223

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.

11voto

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.

3voto

John Mulder Punkte 9047

Std::pair ist für einige der anderen Containerklassen in der STL sehr nützlich.

Zum Beispiel:

std::map<>
std::multimap<> 

Beide speichern std::

Bei der Verwendung von map und multimap greifen Sie häufig auf die Elemente über einen Zeiger auf ein Paar zu.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X