Unterschied zwischen std :: pair und std :: tuple mit nur zwei Mitgliedern?

88

Gibt es einen Unterschied zwischen einem std::pairund einem std::tuplemit nur zwei Mitgliedern? (Neben dem Offensichtlichen, das std::pairzwei und nur zwei Mitglieder erfordert und tuplemehr oder weniger haben kann ...)

Casey
quelle

Antworten:

83

Es gibt einige Unterschiede:

  1. std::tuplekann niemals durch seine Standard-Layout (zumindest ist es nicht erforderlich , von der Norm sein). Jedes std::pair<T, Y>ist Standard-Layout, wenn beide Tund YStandard-Layout sind.

  2. Es ist ein bisschen einfacher, den Inhalt von a pairals a zu bekommen tuple. Sie müssen in dem tupleFall einen Funktionsaufruf verwenden , während der pairFall nur ein Mitgliedsfeld ist.

Aber das war es schon.

Nicol Bolas
quelle
4
"Es ist ein bisschen einfacher, die Daten aus einem Paar herauszuholen als aus einem Tupel. Ein bisschen." Ich bemerkte. : P Obwohl .firstund .secondpraktisch, bieten sie keine Hilfe, wenn ein drittes (oder mehr) Mitglied (e) für eine Codeänderung erforderlich sind. Mir ist aufgefallen, dass ich in der Regel std::getunabhängig von Getters verwende, sodass ich nicht alles ändern muss, nur die Datentypen und alle make_pairAufrufe zu make_tupleAnrufen.
Casey
Es scheint , dass std::mapAnwendungen std::pair<const Key,T>als value_typeauch in C ++ 11. Wo genau werden Tupel verwendet std::map?
nknight
@nknight: ... Ich habe keine Ahnung, warum ich das gesagt habe. Oder was ich stattdessen sagen wollte std::map.
Nicol Bolas
1
@ Yakk: Ähm, ich drücke "." und meine IDE zeigt eine Liste der Mitglieder an. Ich hätte nicht gedacht, dass die Leute das brauchen.
Nicol Bolas
1
Ich frage mich, ob die strukturierte Bindung in c ++ 17 bereits 1 und 2 Punkte dieser Antwort ungültig macht. Wenn ja, fügen Sie bitte auch eine C ++ 17-Version hinzu.
Sanddorn
28

Dies ist eine sehr späte Antwort. Beachten Sie jedoch, dass std::pairdie Größe aufgrund der Definition mit Elementvariablen nicht mithilfe der Optimierung für leere Basisklassen optimiert werden kann ( firstund secondunterschiedliche Adressen belegen muss, selbst wenn eine oder beide eine leere Klasse sind). Dies wird durch die jeweiligen Ausrichtungsanforderungen noch verschärft second_type, sodass das Ergebnis im schlimmsten Fall im std::pairGrunde doppelt so groß ist, wie es sein muss.

std::tupleErmöglicht nur den Zugriff über Hilfsfunktionen, sodass er von beiden Typen abgeleitet werden kann, wenn der eine oder andere leer ist, wodurch Overhead gespart wird. Zumindest die Implementierung von GCC macht dies definitiv ... Sie können die Header durchsehen, um dies zu überprüfen, aber es gibt auch dies als Beweis.

Stephen Lin
quelle
4
Natürlich sollte C ++ 20[[no_unique_address]] den std::pairNachteil beseitigen .
Deduplikator
27

Ein std::tuple‚s Name ist länger (ein zusätzliches Zeichen). Weitere dieser Zeichen werden mit der rechten Hand eingegeben, sodass die meisten Benutzer sie leichter eingeben können.

Das heißt, std::pairkann nur zwei Werte haben - nicht null, eins, drei oder mehr. ZWEI Werte. Ein Tupel hat jedoch fast keine semantische Begrenzung der Anzahl von Werten. Ein std::pairtypensicherer Typ ist daher genauer, wenn Sie tatsächlich ein Wertepaar angeben möchten.

Arafangion
quelle
18
LOL! Genial, dass Sie überlegen, wie es geschrieben wird! Ich möchte jedoch darauf hinweisen, dass ich wahrscheinlich "Paar" mehr als 20% schneller als "Tupel" tippe. Dies liegt daran, dass meine Hände jedes Zeichen alternativ eingeben, dh. RHS: p, LHS: a, RHS: i, LHS: r. Zumindest für mich finde ich das einfacher! - aber du bekommst immer noch +1!
Richard Corden
14
" Ein std :: pair ist daher ein genauerer typsicherer Typ, der verwendet werden soll, wenn Sie tatsächlich ein Wertepaar angeben möchten. " Es ist nicht typsicherer oder "genauer", es signalisiert nur (wohl) Absichten direkter.
ildjarn
1
@Arafangion: std::tuple<>ist auch typsicher (wie könnte es nicht sein?) Und unterscheidet 2sich semantisch nicht von pair.
ildjarn
1
" Ein std :: pair ist daher ein genauerer, typsicherer Typ ". Und ich denke, jeder englische Sprecher wird "pair" und "two" als völlig synonym betrachten. : -]
ildjarn
3
@ildjam: Wir spalten hier Haare, aber nein, sie sind nicht ganz synonym. Wenn Sie "zwei Schuhe" sagen, meinen Sie "zwei Schuhe, die durchaus beide linke Schuhe sein könnten", oder meinen Sie "ein Paar Schuhe" (von denen einer immer links und der andere immer rechts ist) ?
Arafangion
8

Beachten Sie, dass mit C ++ 17 dieselbe Schnittstelle verwendet werden kann, um Daten sowohl aus Paaren als auch aus Tupeln mit zwei Elementen zu lesen.

auto [a, b] = FunctionToReturnPairOrTuple();

Keine Notwendigkeit zu verwenden get<>:)

bhardwajs
quelle
3

Für das, was es wert ist, finde ich die GDB-Ausgabe von std :: tuple weitaus schwieriger zu lesen. Wenn Sie mehr als 2 Werte benötigen, funktioniert std :: pair natürlich nicht, aber ich halte dies für einen Punkt zugunsten von Strukturen.

tgoodhart
quelle
Deshalb wickle ich, wenn ich sie im Unterricht benutze, die Bruttolinie std::get<0>(tupleName)in einen Getter ein; GetX()ist viel einfacher zu lesen und kürzer. Es hat einen kleinen Nachteil, dass constjemand so etwas Dummes tun kann , wenn man vergisst, es zu einer Methode zu machen : GetX() = 20;.
Casey