Lvalues i Rvalues (C++)

Każde wyrażenie języka C++ ma typ i należy do kategorii wartości. Kategorie wartości są podstawą reguł, które kompilatory muszą przestrzegać podczas tworzenia, kopiowania i przenoszenia obiektów tymczasowych podczas obliczania wyrażenia.

Standard C++17 definiuje kategorie wartości wyrażeń w następujący sposób:

  • Glvalue to wyrażenie, którego ocena określa tożsamość obiektu, pola bitowego lub funkcji.
  • Prvalue to wyrażenie, którego ocena inicjuje obiekt lub pole bitowe lub oblicza wartość operandu operatora, jak określono w kontekście, w którym się pojawia.
  • Xvalue to wartość glvalue , która określa obiekt lub pole bitowe, którego zasoby mogą być ponownie używane (zwykle dlatego, że zbliża się do końca okresu istnienia). Przykład: Niektóre rodzaje wyrażeń obejmujących odwołania rvalue (8.3.2) dają wartości xvalue, takie jak wywołanie funkcji, której typem zwracanym jest odwołanie rvalue lub rzutowanie do typu odwołania rvalue do typu odwołania rvalue.
  • Wartość lvalue to glvalue , która nie jest wartością xvalue.
  • Wartość rvalue jest wartością prvalue lub xvalue.

Na poniższym diagramie przedstawiono relacje między kategoriami:

Diagram of C++ expression value categories.

Diagram zaczyna się od pola oznaczonego wyrażeniem, które ma dwie elementy podrzędne: glvalue i rvalue. glvalue ma dwie elementy podrzędne: lvalue i xvalue. rvalue ma dwie elementy podrzędne: prvalue i xvalue; xvalue jest również elementem podrzędnym glvalue.

Element lvalue ma adres, do którego program może uzyskać dostęp. Przykłady wyrażeń lvalue obejmują nazwy zmiennych, w tym const zmienne, elementy tablicy, wywołania funkcji zwracające odwołanie lvalue, pola bitów, związki i składowe klasy.

Wyrażenie prvalue nie ma adresu, który jest dostępny dla programu. Przykłady wyrażeń prvalue obejmują literały, wywołania funkcji zwracające typ niereferencji i obiekty tymczasowe tworzone podczas obliczania wyrażenia, ale dostępne tylko przez kompilator.

Wyrażenie xvalue ma adres, który nie jest już dostępny dla programu, ale może służyć do inicjowania odwołania rvalue, który zapewnia dostęp do wyrażenia. Przykłady obejmują wywołania funkcji zwracające odwołanie rvalue oraz indeks dolny tablicy, składowy i wskaźnik do wyrażeń składowych, w których tablica lub obiekt jest odwołaniem rvalue.

Przykład

W poniższym przykładzie pokazano kilka poprawnych i nieprawidłowych użycia wartości lvalue i 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
}

Uwaga

Przykłady w tym temacie ilustrują poprawne i nieprawidłowe użycie, gdy operatory nie są przeciążone. Przeciążając operatory, można wykonać wyrażenie, takie jak j * 4 lvalue.

Terminy lvalue i rvalue są często używane podczas odwoływania się do odwołań do obiektów. Aby uzyskać więcej informacji na temat odwołań, zobacz Deklarator odwołań Lvalue: & iRvalue Reference Deklarator: &&.

Zobacz też

Podstawowe pojęcia
Deklarator odwołania do wartości L: &
Deklarator odwołania do wartości R: &&