wake-up-neo.com

Fehler: Ungültige Initialisierung einer nicht konstanten Referenz vom Typ "int &" von einem Wert vom Typ "int"

Falsche Form:

int &z = 12;

Richtige Form:

int y;
int &r = y;

Frage:
Warum ist der erste Code falsch? Was ist das "Bedeutung" des Fehlers im Titel?

77
Aquarius_Girl

C++ 03 3.10/1 sagt: "Jeder Ausdruck ist entweder ein lWert oder ein rWert." Es ist wichtig sich daran zu erinnern, dass Wertigkeit im Vergleich zu Wertigkeit eine Eigenschaft von Ausdrücken ist, nicht von Objekten.

Lvalues ​​benennt Objekte, die über einen einzelnen Ausdruck hinaus bestehen. Beispiel: obj, *ptr, ptr[index] Und ++x Sind alles Werte.

R-Werte sind temporäre Werte, die am Ende des vollständigen Ausdrucks, in dem sie leben, verdunsten ("am Semikolon"). Beispiel: 1729, x + y, std::string("meow") und x++ Sind alles Werte.

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 I-Wert, andernfalls ein R-Wert.

 &obj; //  valid
 &12;  //invalid
119
BruceAdi
int &z = 12;

Auf der rechten Seite wird ein temporäres Objekt vom Typ int aus dem ganzzahligen Literal 12 Erstellt, das temporäre Objekt 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 existieren soll, muss es zuerst erstellt werden. Da das Objekt unbenannt ist, ist es 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 einen konstanten Verweis gebunden werden. Dies bedeutet, dass Sie dies tun können:

const int &z = 12; //ok

C++ 11 und Rvalue Referenz:

Der Vollständigkeit halber möchte ich hinzufügen, dass C++ 11 rvalue-reference eingeführt hat, das an temporäre Objekte gebunden werden kann. In C++ 11 können Sie also Folgendes schreiben:

int && z = 12; //C+11 only 

Beachten Sie, dass es && Anstelle von & Gibt. Beachten Sie auch, dass const nicht mehr benötigt wird, obwohl das Objekt, an das z bindet, ein temporäres Objekt ist, das aus dem Integral-Literal 12 Erstellt wurde. .

Seit C++ 11 rvalue-reference eingeführt hat, heißt int& Nun lvalue-reference.

46
Nawaz

12 Ist eine Konstante zur Kompilierungszeit, die im Gegensatz zu den von int& Referenzierten Daten nicht geändert werden kann. Was Sie können tun, ist

const int& z = 12;

Nicht konstante und konstante Referenzbindung folgen unterschiedlichen Regeln

Dies sind die Regeln der C++ - Sprache:

  • ein Ausdruck bestehend aus einer wörtlichen Zahl (12) ist ein "Wert"
  • es ist nicht erlaubt, eine nicht konstante Referenz mit einem r-Wert zu erstellen: int &ri = 12; ist schlecht geformt
  • es ist zulässig, eine konstante Referenz mit einem Wert zu erstellen: In diesem Fall wird ein unbenanntes Objekt vom Compiler erstellt. Dieses Objekt bleibt so lange bestehen, wie die Referenz selbst existiert.

Sie müssen verstehen, dass dies C++ - Regeln sind. Sie sind es einfach.

Es ist einfach, eine andere Sprache, beispielsweise C++ ', mit leicht unterschiedlichen Regeln zu erfinden. In C++ 'wäre es zulässig, eine nicht konstante Referenz mit einem r-Wert zu erstellen. Hier gibt es nichts Inkonsistentes oder Unmögliches.

Aber es würde einen riskanten Code zulassen, bei dem der Programmierer möglicherweise nicht das bekommt, was er beabsichtigt hat, und C++ - Designer haben zu Recht beschlossen, dieses Risiko zu vermeiden.

4
curiousguy

Referenzen sind "versteckte Zeiger" (nicht null) auf Dinge, die sich ändern können (Werte). Sie können sie nicht zu einer Konstanten definieren. Es sollte eine "variable" Sache sein.

BEARBEITEN::

Ich denke an

int &x = y;

als fast gleichwertig mit

int* __px = &y;
#define x (*__px)

woher __px ist ein neuer Name, und der #define x funktioniert nur innerhalb des Blocks, der die Deklaration von x enthält.