Betrachten Sie diesen Code:
#include <iostream>
#include <functional>
int xx = 7;
template<class T>
void f1(T arg)
{
arg += xx;
}
template<class T>
void f2(T arg)
{
arg = xx;
}
int main()
{
int j;
j=100;
f1(std::ref(j));
std::cout << j << std::endl;
j=100;
f2(std::ref(j));
std::cout << j << std::endl;
}
Bei Ausführung wird dieser Code ausgegeben
107
100
Ich hätte erwartet, dass der zweite Wert 7 statt 100 ist.
Was vermisse ich?
Antworten:
Eine kleine Modifikation
f2
liefert den Hinweis:template<class T> void f2(T arg) { arg.get() = xx; }
Dies macht jetzt, was Sie erwarten.
Dies ist passiert, weil
std::ref
einstd::reference_wrapper<>
Objekt zurückgegeben wird. Der Zuweisungsoperator, der den Wrapper neu bindet . (siehe http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D )Es wird keine Zuordnung zur umschlossenen Referenz vorgenommen.
In diesem
f1
Fall funktioniert alles wie erwartet, da astd::reference_wrapper<T>
einen Konvertierungsoperator für bereitstelltT&
, der an die implizite rechte Seite vonint
s implizit bindetoperator+
.quelle
reference_wrapper
hatoperator =
und einen nicht expliziten Konstruktor, siehe Dokumentation .Auch wenn es überraschend ist, ist es das normale Verhalten:
f2
bindet den lokalen reference_wrapper erneut anxx
.quelle
Lokal
arg
bezieht sich jetzt auf (gelesen als Bindungen mit)xx
. (Und nicht mehr bezieht sich aufj
)Implizit
operator T& ()
wird angewendet, um mit dem Argument vonoperator +=
übereinzustimmen, und daher wird die Addition für das referenzierte Objekt durchgeführt, dj
. H.Das beobachtete Verhalten ist also korrekt.
quelle