Falsche Form:
int &z = 12;
Richtige Form:
int y;
int &r = y;
Frage :
Warum ist der erste Code falsch? Was ist die " Bedeutung " des Fehlers im Titel?
(ostringstream() << "x=" << x).str()
Falsche Form:
int &z = 12;
Richtige Form:
int y;
int &r = y;
Frage :
Warum ist der erste Code falsch? Was ist die " Bedeutung " des Fehlers im Titel?
(ostringstream() << "x=" << x).str()
Antworten:
In C ++ 03 3.10 / 1 heißt es: "Jeder Ausdruck ist entweder ein l-Wert oder ein r-Wert." Es ist wichtig, sich daran zu erinnern, dass Wertigkeit gegenüber Wertigkeit eine Eigenschaft von Ausdrücken ist, nicht von Objekten.
L-Werte benennen Objekte, die über einen einzelnen Ausdruck hinaus bestehen bleiben. Zum Beispiel obj
, *ptr
, ptr[index]
und ++x
sind alle lvalues.
R-Werte sind Provisorien, die am Ende des vollständigen Ausdrucks, in dem sie leben, verdunsten ("am Semikolon"). Beispielsweise,1729
, x + y
, std::string("meow")
und x++
sind alle rvalues.
Die Adresse des Operators verlangt, dass sein "Operand ein Wert ist". Wenn wir die Adresse eines Ausdrucks nehmen könnten, wäre der Ausdruck ein l-Wert, andernfalls ein r-Wert.
&obj; // valid
&12; //invalid
int & = 12;
ungültig ist, sagt der Standard, dass ein String-Literal ein l-Wert ist, andere Literale sind r-Werte.
std::string("meow")
Konstruiert jedoch ein Objekt vom Typ std::string
und liefert einen r-Wert, der dieses Objekt bezeichnet, 1729
keine Nebenwirkungen hat und einen Wert liefert 1729 als Wert des Typs int
.
(const int&)1;
int &z = 12;
Auf der rechten Seite int
wird aus dem integralen Literal ein temporäres Objekt vom Typ erstellt , das temporäre Objekt 12
kann jedoch nicht an eine nicht konstante Referenz gebunden werden. Daher der Fehler. Es ist dasselbe wie:
int &z = int(12); //still same error
Warum wird eine temporäre erstellt? Da sich eine Referenz auf ein Objekt im Speicher beziehen muss und ein Objekt vorhanden sein muss, muss es zuerst erstellt werden. Da das Objekt unbenannt ist, handelt es sich um ein temporäres Objekt. Es hat keinen Namen. Aus dieser Erklärung wurde ziemlich klar, warum der zweite Fall in Ordnung ist.
Ein temporäres Objekt kann an eine const-Referenz gebunden werden. Dies bedeutet, dass Sie Folgendes tun können:
const int &z = 12; //ok
Der Vollständigkeit halber möchte ich hinzufügen, dass C ++ 11 eine rvalue-Referenz eingeführt hat, die an ein temporäres Objekt gebunden werden kann. In C ++ 11 können Sie also Folgendes schreiben:
int && z = 12; //C+11 only
Beachten Sie, dass es &&
intead von gibt &
. Beachten Sie auch, dass dies const
nicht mehr benötigt wird, obwohl das Objekt, an das z
gebunden wird, ein temporäres Objekt ist, das aus einem Integral-Literal erstellt wurde 12
.
Da C ++ 11 rvalue-reference eingeführt hat , int&
wird es nun als lvalue-reference bezeichnet .
12
ist eine Konstante zur Kompilierungszeit, die im Gegensatz zu den Daten, auf die verwiesen wird, nicht geändert werden kann int&
. Was Sie tun können , ist
const int& z = 12;
void f( vector<int> const & )
, die idiomatisch ist, um einen Vektor zu übergeben, der nicht geändert werden soll. Das Problem ist jetzt, dass f( vector<int>(5) )
dies falsch wäre und der Benutzer eine andere Überlastung bereitstellen müsste, void f( vector<int> v ) { f(v); }
was trivial ist.
f( vector<int>(5) )
der Compiler eine temporäre und bindet dann den Verweis auf diese temporäre und ähnliche wenn es eine implizite Konvertierung von 5
direkt gab. Dies ermöglicht dem Compiler, eine einzelne Signatur für die Funktion zu generieren, und ermöglicht eine Einzelbenutzerimplementierung der Funktion. Von da an wird ein ähnliches Verhalten für den Rest der Verwendung konstanter Referenzen zur Konsistenz definiert.
T const & r = *ptr;
jede spätere Verwendung r
in der Funktion kann durch ersetzt werden *ptr
und r
muss zur Laufzeit nicht vorhanden sein). oder es muss möglicherweise implementiert werden, indem die Adresse des Objekts beibehalten wird, das es als Aliase verwendet (speichern Sie eine Referenz als Mitglied eines Objekts) - das als automatisch referenzierter Zeiger implementiert ist.
Dies sind die Regeln der C ++ - Sprache:
12
Literalzahl ) besteht, ist ein "rWert".int &ri = 12;
ist schlecht geformtSie müssen verstehen, dass dies C ++ - Regeln sind. Sie sind es einfach.
Es ist einfach, eine andere Sprache zu erfinden, beispielsweise C ++ ', mit leicht unterschiedlichen Regeln. In C ++ 'wäre es zulässig, eine nicht konstante Referenz mit einem r-Wert zu erstellen. Hier ist nichts inkonsistent oder unmöglich.
Aber es würde einen riskanten Code ermöglichen, bei dem der Programmierer möglicherweise nicht das bekommt, was er beabsichtigt hat, und C ++ - Designer haben zu Recht beschlossen, dieses Risiko zu vermeiden.
Verweise sind "versteckte Zeiger" (nicht null) auf Dinge, die sich ändern können (lWerte). Sie können sie nicht als Konstante definieren. Es sollte eine "variable" Sache sein.
BEARBEITEN::
ich denke an
int &x = y;
als fast gleichwertig mit
int* __px = &y;
#define x (*__px)
wo __px
ist ein neuer Name, und das #define x
funktioniert nur innerhalb des Blocks, der die x
Referenzdeklaration enthält.
const
:)
const