Lvalues und Rvalues (C++)

Jeder C++-Ausdruck hat einen Typ und gehört zu einer Wertkategorie. Die Wertkategorien sind die Grundlage für Regeln, die Compiler beim Erstellen, Kopieren und Verschieben temporärer Objekte während der Ausdrucksauswertung befolgen müssen.

Der C++17-Standard definiert Ausdruckswertkategorien wie folgt:

  • Ein Glvalue ist ein Ausdruck, dessen Auswertung die Identität eines Objekts, eines Bitfelds oder einer Funktion bestimmt.
  • Ein Wert ist ein Ausdruck, dessen Auswertung ein Objekt oder ein Bitfeld initialisiert oder den Wert des Operanden eines Operators berechnet, wie im Kontext angegeben, in dem er angezeigt wird.
  • Ein X-Wert ist ein Glvalue , der ein Objekt oder Bitfeld angibt, dessen Ressourcen wiederverwendet werden können (in der Regel weil er sich am Ende seiner Lebensdauer befindet). Beispiel: Bestimmte Arten von Ausdrücken mit Rvalue-Verweisen (8.3.2) liefern X-Werte, z. B. einen Aufruf einer Funktion, deren Rückgabetyp ein Rvalue-Bezug ist, oder eine Umwandlung in einen Rvalue-Bezugstyp.
  • Ein lvalue ist ein Glvalue , der kein X-Wert ist.
  • Ein Wert ist ein Wert oder ein X-Wert.

Das folgende Diagramm veranschaulicht die Beziehungen zwischen den Kategorien:

Diagram of C++ expression value categories.

Das Diagramm beginnt mit einem Beschriftungsausdruck mit zwei untergeordneten Elementen: glvalue und rvalue. glvalue hat zwei untergeordnete Elemente: lvalue und xvalue. "rvalue" hat zwei untergeordnete Elemente: "Prvalue" und "xvalue"; "xvalue" ist auch ein untergeordnetes Element von "glvalue".

Ein lvalue hat eine Adresse, auf die Ihr Programm zugreifen kann. Beispiele für lvalue-Ausdrücke sind Variablennamen, einschließlich const Variablen, Arrayelemente, Funktionsaufrufe, die einen lvalue-Verweis, Bitfelder, Unions- und Klassenmber zurückgeben.

Ein Prvalue-Ausdruck hat keine Adresse, die von Ihrem Programm zugänglich ist. Beispiele für Prvalue-Ausdrücke sind Literale, Funktionsaufrufe, die einen Nichtreferenztyp zurückgeben, und temporäre Objekte, die während der Ausdrucksauswertung erstellt werden, aber nur vom Compiler zugänglich sind.

Ein xvalue-Ausdruck verfügt über eine Adresse, auf die Ihr Programm nicht mehr zugreifen kann, aber zum Initialisieren eines Rvalue-Verweises verwendet werden kann, der Zugriff auf den Ausdruck ermöglicht. Beispiele sind Funktionsaufrufe, die einen Rvalue-Verweis zurückgeben, und das Array-Subscript, Member und Zeiger auf Memberausdrücke, bei denen das Array oder Objekt ein Rvalue-Verweis ist.

Beispiel

Das folgende Beispiel zeigt mehrere korrekte und falsche Verwendungen von lvalues und rvalues:

// lvalues_and_rvalues2.cpp
int main()
{
    int i, j, *p;

    // Correct usage: the variable i is an lvalue and the literal 7 is a prvalue.
    i = 7;

    // Incorrect usage: The left operand must be an lvalue (C2106).`j * 4` is a prvalue.
    7 = i; // C2106
    j * 4 = 7; // C2106

    // Correct usage: the dereferenced pointer is an lvalue.
    *p = i;

    // Correct usage: the conditional operator returns an lvalue.
    ((i < 3) ? i : j) = 7;

    // Incorrect usage: the constant ci is a non-modifiable lvalue (C3892).
    const int ci = 7;
    ci = 9; // C3892
}

Hinweis

Die Beispiele zu diesem Thema veranschaulichen die korrekte und falsche Verwendung, wenn Operatoren nicht überladen werden. Indem Sie Operatoren überladen, können Sie aus einem Ausdruck wie j * 4 einen lvalue machen.

Die Begriffe "lvalue " und "rvalue " werden häufig verwendet, wenn Sie auf Objektverweise verweisen. Weitere Informationen zu Verweisen finden Sie unter Lvalue Reference Declarator: & und Rvalue Reference Declarator: &&&.

Siehe auch

Grundlegende Konzepte
Lvalue-Verweisdeklarator: &
Rvalue-Verweisdeklarator: &&