Ich habe einige Fragen zu diesem Programm:
#include <iostream>
#include <type_traits>
#include <functional>
using namespace std;
template <typename T> void foo ( T x )
{
auto r=ref(x);
cout<<boolalpha;
cout<<is_same<T&,decltype(r)>::value;
}
int main()
{
int x=5;
foo (x);
return 0;
}
Die Ausgabe ist:
false
Ich möchte wissen, wenn std::ref
es die Referenz eines Objekts nicht zurückgibt, was macht es dann? Was ist der Unterschied zwischen:
T x;
auto r = ref(x);
und
T x;
T &y = x;
Ich möchte auch wissen, warum dieser Unterschied besteht. Warum brauchen wir std::ref
oder std::reference_wrapper
wenn wir Referenzen haben (dh T&
)?
x = y;
in beiden Fällen tun ?Antworten:
Well erstellt
ref
ein Objekt des entsprechendenreference_wrapper
Typs, um einen Verweis auf ein Objekt zu enthalten. Was bedeutet, wenn Sie sich bewerben:Dies gibt einen
reference_wrapper
und keinen direkten Verweis aufx
(dhT&
) zurück. Diesreference_wrapper
(dhr
) gilt stattdessenT&
.A
reference_wrapper
ist sehr nützlich, wenn Siereference
ein Objekt emulieren möchten, das kopiert werden kann (es ist sowohl kopierkonstruierbar als auch kopierzuweisbar ).In C ++, wenn Sie einen Verweis (sagen wir erstellen
y
) zu einem Objekt (sagen wirx
), danny
undx
teilen die gleiche Basisadresse . Darüber hinausy
kann nicht auf ein anderes Objekt verweisen. Sie können auch kein Array von Referenzen erstellen, dh Code wie dieser löst einen Fehler aus:Dies ist jedoch legal:
Wenn Sie über Ihr Problem sprechen
cout << is_same<T&,decltype(r)>::value;
, lautet die Lösung:Lassen Sie mich Ihnen ein Programm zeigen:
Hier lernen wir drei Dinge kennen:
Ein
reference_wrapper
Objekt (hierr
) kann verwendet werden, um ein Array von Referenzen zu erstellen, mit denen dies nicht möglich warT&
.r
verhält sich tatsächlich wie eine echte Referenz (sehen Sie, wier.get()=70
sich der Wert von geändert haty
).r
ist nicht dasselbe wieT&
aberr.get()
ist. Dies bedeutet, dassr
gilt,T&
dh wie der Name schon sagt, ein Wrapper um eine Referenz istT&
.Ich hoffe, diese Antwort ist mehr als genug, um Ihre Zweifel zu erklären.
quelle
reference_wrapper
kann neu zugewiesen werden , aber es kann nicht "auf mehr als ein Objekt verweisen". 2/3: Fairer Punkt darüber, wo dies.get()
angemessen ist - aber ohne Suffixr
kann genauso verwendet werden wieT&
in Fällen, in denenr
die Konvertierungoperator
eindeutig aufgerufen werden kann -, sodass.get()
in vielen Fällen kein Aufruf erforderlich ist, einschließlich mehrerer in Ihrem Code (der schwer zu lesen ist) wegen Platzmangels).reference_wrapper
kann eine Reihe von Referenzen enthalten, wenn Sie sich nicht sicher sind, können Sie es selbst versuchen. Plus.get()
wird verwendet, wenn Sie den Wert des Objekts ändern möchten, das sichreference_wrapper
befindet, dhr=70
illegal ist, sodass Sie es verwenden müssenr.get()=70
. Versuchen Sie es selbst !!!!!!int a[4]{1, 2, 3, 4}; int (&b)[4] = a;
? reference_wrapper ist hier nichts Besonderes, da nativeT&
funktioniert .wrapper
in einen Container gehen können. Das ist praktisch, aber ich denke, die Leute interpretieren dies falsch als fortgeschrittener als es wirklich ist. Wenn ich eine Reihe von 'Refs' will, überspringe ich normalerweise den Mittelsmann mitvector<Item *>
, worauf eswrapper
ankommt ... und hoffe, dass die Anti-Zeiger-Puristen mich nicht finden. Die überzeugenden Anwendungsfälle dafür sind unterschiedlich und komplexer.std::reference_wrapper
wird von Standardeinrichtungen erkannt, Objekte in Referenzkontexten als Referenz übergeben zu können.Sie können beispielsweise
std::bind
dasstd::ref()
zu etwas aufnehmen, es nach Wert übertragen und später wieder in eine Referenz entpacken.Dieses Snippet gibt Folgendes aus:
Der Wert von
i
wurdef1
an dem Punkt gespeichert (nach Wert genommen), an dem er initialisiert wurde,f2
hat jedoch einen By-std::reference_wrapper
Wert beibehalten und verhält sich daher so, als hätte er einen aufgenommenint&
.quelle
std::ref(T)
gibt a zurückstd::reference_wrapper
. Es ist kaum mehr als ein umhüllter Zeiger, wird aber von der Bibliothek als "Hey, ich soll eine Referenz sein! Bitte verwandeln Sie mich wieder in einen, wenn Sie fertig sind, mich herumzugeben" erkannt.Eine Referenz (
T&
oderT&&
) ist ein spezielles Element in der C ++ - Sprache. Es ermöglicht die Manipulation eines Objekts durch Referenz und hat spezielle Anwendungsfälle in der Sprache. Beispielsweise können Sie keinen Standardcontainer erstellen, der Referenzen enthält: Ervector<T&>
ist fehlerhaft und generiert einen Kompilierungsfehler.A
std::reference_wrapper
hingegen ist ein C ++ - Objekt, das eine Referenz enthalten kann. Als solches können Sie es in Standardcontainern verwenden.std::ref
ist eine Standardfunktion, die einstd::reference_wrapper
Argument zurückgibt . In der gleichen Idee,std::cref
kehrtstd::reference_wrapper
zu einer const - Referenz.Eine interessante Eigenschaft von a
std::reference_wrapper
ist, dass es eine hatoperator T& () const noexcept;
. Das heißt, selbst wenn es sich um ein echtes Objekt handelt , kann es automatisch in die Referenz konvertiert werden, die es enthält. So:operator T& () const noexcept;
kann es überall dort verwendet werden, wo Sie eine Referenz verwenden können, da es automatisch in diese konvertiert wird.quelle
operator T& ()
welche anderen 2 Antworten nicht erwähnt wurden.