Close Menu
    Ciekawe

    Opera Portable – przeglądarka internetowa na pendrive bez instalacji

    2026-03-09

    doPDF – wirtualna drukarka do konwersji dokumentów na PDF

    2026-03-08

    Kaspersky Free – podstawowa ochrona antywirusowa za darmo

    2026-03-07
    Facebook X (Twitter) Instagram
    CPP Polska
    Facebook X (Twitter) Instagram
    • Biznes

      Programy VPN – ranking, porównanie i poradnik wyboru (2026)

      2026-02-26

      Obrót, przychód i dochód firmy – czym się różnią i jak je obliczyć?

      2026-02-16

      Restrukturyzacja i upadłość firmy – na czym polegają i jakie są konsekwencje?

      2026-02-14

      Składki ZUS dla firmy jednoosobowej w 2025 roku – ile wynoszą i jak je obliczyć?

      2026-01-28

      Co powinna zawierać pieczątka firmy jednoosobowej? Wymogi prawne i wzór

      2025-12-28
    • Technologie

      Opera Portable – przeglądarka internetowa na pendrive bez instalacji

      2026-03-09

      doPDF – wirtualna drukarka do konwersji dokumentów na PDF

      2026-03-08

      Kaspersky Free – podstawowa ochrona antywirusowa za darmo

      2026-03-07

      PeaZip – darmowy program do otwierania archiwów ZIP i RAR

      2026-03-05

      Jak oglądać filmy VR na komputerze? Wymagania i instrukcja

      2026-03-04
    • Programowanie

      Maszyna stanów oparta o std::variant

      2025-10-07

      std::deque w C++ – kiedy wybrać dwukierunkową kolejkę zamiast vectora

      2025-10-07

      Tablice w C++ od podstaw – deklaracja, inicjalizacja, iteracja i typowe pułapki

      2025-10-07

      itoa i std::to_chars – konwersja liczb na tekst bez narzutu wydajności

      2025-10-07

      strcpy vs strncpy vs std::string – bezpieczne kopiowanie łańcuchów w C++

      2025-10-07
    • Inne

      eSIM w Mobile Vikings – jak wirtualna karta SIM daje Ci wolność bez plastiku, kuriera i wychodzenia z domu

      2025-12-16

      Jak prowadzić blog programistyczny i dzielić się wiedzą?

      2025-06-28
    • Programy VPN – ranking
    CPP Polska
    Home»C++»Kategorie wartości w C++: lvalue, rvalue, prvalue – podział wyrażeń
    C++

    Kategorie wartości w C++: lvalue, rvalue, prvalue – podział wyrażeń

    Oskar KlimkiewiczBy Oskar KlimkiewiczBrak komentarzy5 Mins Read
    Share Facebook Twitter LinkedIn Email Copy Link
    Follow Us
    RSS
    a computer screen with a bunch of lines on it
    Share
    Facebook Twitter LinkedIn Email Copy Link

    Kategorie wartości w C++ – lvalue, rvalue, prvalue – podział wyrażeń

    W języku C++ każda ekspresja (wyrażenie) posiada określoną kategorię wartości, która decyduje o sposobie jej przetwarzania przez kompilator. Podział na lvalue, rvalue, prvalue i inne kategorie jest fundamentalny dla zrozumienia mechanizmów takich jak semantyka przenoszenia, przekazywanie argumentów czy optymalizacje. Współczesny standard C++ (od wersji 11) definiuje pięć kategorii wartości, które tworzą hierarchię opartą o dwie niezależne właściwości: posiadanie tożsamości oraz możliwość przenoszenia (movability). Poniższe omówienie szczegółowo analizuje każdą kategorię, ich relacje oraz praktyczne implikacje.

    Historyczny rozwój kategorii wartości

    Przed standardem C++11 istniał jedynie binarny podział wartości na lvalue i rvalue, oparty na kryterium występowania po lewej stronie operatora przypisania. Ekspresje modyfikowalne (np. zmienne) klasyfikowano jako lvalue, natomiast tymczasowe obiekty (np. wyniki operacji) jako rvalue. Ta uproszczona klasyfikacja okazała się niewystarczająca dla wprowadzonej w C++11 semantyki przenoszenia, która umożliwia efektywne przekazywanie zasobów bez zbędnego kopiowania.

    Nowy model, opisany w standardzie ISO/IEC 14882:2011, wprowadził trzy podstawowe kategorie:

    1. lvalue (np. zmienne, referencje);
    2. prvalue (czyste r-wartości, np. literały);
    3. xvalue (eXpiring values, np. obiekty zwracane przez std::move()).
      Dodatkowo zdefiniowano dwie kategorie złożone:
    • glvalue (generalized lvalue) = lvalue + xvalue;
    • rvalue = prvalue + xvalue.
      Hierarchię tę ilustruje diagram relacji:
    
    expression
       /      \
    glvalue   rvalue
      /  \     /  \
    lvalue xvalue prvalue
    

    Kluczową innowacją było rozdzielenie pojęć tożsamości (adresowalność) i przenoszalności, co umożliwiło precyzyjne sterowanie ruchem obiektów.

    Podstawowe kategorie wartości

    Lvalue (Left value)

    Definicja – Ekspresje posiadające trwałą tożsamość (adres w pamięci), które mogą wystąpić po lewej stronie operatora przypisania (o ile nie są const-kwalifikowane). Przykłady:

    • zmienne (np. int x; x jest lvalue);
    • elementy tablic (np. arr);
    • referencje zwracane przez funkcje (np. std::cout << 1);
    • właściwości klas (np. obj.member);
    • ciągi znakowe (np. "Hello").

    Właściwości –

    • możliwość pobrania adresu (&x);
    • możliwość modyfikacji (o ile niezakwalifikowane jako const);
    • długi czas życia – istnieją poza wyrażeniem, w którym zostały użyte.

    Przykład błędnego użycia:
    const int c = 42; c = 10; // Błąd: c jest const-lvalue!

    Prvalue (Pure rvalue)

    Definicja – Tymczasowe obiekty bez tożsamości, które służą do inicjalizacji lub obliczeń. Występują wyłącznie po prawej stronie przypisania. Przykłady:

    • literały (np. 5, 3.14, true);
    • wyniki operacji arytmetycznych (np. x + 1);
    • funkcje zwracające wartość (np. str.substr(0, 2));
    • konstrukcje tymczasowe (np. std::string("temp")).

    Właściwości –

    • brak adresu (&(x + 1) jest niepoprawny);
    • krótki czas życia – niszczone po zakończeniu wyrażenia;
    • automatyczna konwersja do xvalue w kontekstach wymagających przenoszenia (tzw. materializacja).

    Przykład materializacji:
    int&& r = 42; // prvalue '42' staje się xvalue w inicjalizacji

    Xvalue (eXpiring value)

    Definicja – Obiekty posiadające tożsamość, ale których zasoby można bezpiecznie przenieść (przejąć), ponieważ są „u kresu życia”. Powstają głównie poprzez:

    • wywołanie std::move() (np. std::move(x));
    • rzutowanie na referencję do rvalue (np. static_cast<int&&>(y));
    • dostęp do składowych obiektów tymczasowych (np. getTmp().data).

    Właściwości –

    • adresowalne, ale ich stan może być „unieważniony” po przeniesieniu;
    • umożliwiają optymalizację poprzez unikanie kopiowania (np. w konstruktorach przenoszących).

    Przykład użycia w semantyce przenoszenia:
    std::vector<int> createBigData(); std::vector<int> v = createBigData(); // xvalue z createBigData() pozwala uniknąć kopiowania

    Kategorie złożone

    Glvalue (Generalized lvalue)

    Definiowana jako suma lvalue i xvalue. Wszystkie glvalue posiadają tożsamość, co umożliwia:

    • operacje typu typeid;
    • polimorfizm dynamiczny;
    • dostęp do niekompletnych typów.

    Rvalue

    Składa się z prvalue i xvalue. Kluczową cechą jest przenoszalność (movability), co wykorzystują:

    • referencje do rvalue (T&&);
    • konstruktory przenoszące;
    • operatory przenoszące przypisania.

    Praktyczne implikacje

    Semantyka przenoszenia

    Mechanizm oparty na kategoriach xvalue i prvalue pozwala na optymalizację operacji na obiektach tymczasowych. Funkcja std::move() konwertuje lvalue na xvalue, sygnalizując kompilatorowi możliwość przeniesienia zasobów:

    
    std::string s1 = "Hello";
    std::string s2 = std::move(s1); // s1 staje się xvalue, zasoby są przenoszone
    

    Po takiej operacji s1 pozostaje w poprawnym, ale niezdefiniowanym stanie.

    Doskonałe przekazywanie (perfect forwarding)

    Wzorzec wykorzystujący referencje uniwersalne (T&&), działające zarówno dla lvalue, jak i rvalue. Gwarantuje, że kategoria wartości argumentu jest zachowana podczas przekazywania:

    
    template<typename T>
    void wrapper(T&& arg) {
        // arg zachowuje oryginalną kategorię (lvalue/rvalue)
        process(std::forward<T>(arg)); // std::forward konwertuje do T&&
    }
    

    Kluczową rolę odgrywa tu dedukcja typu oraz zasady collapsing referencji.

    Inicjalizacja a kategorie

    • Bezpośrednia inicjalizacja: T obj(arg); – wykorzystuje kategorię arg;
    • Kopiująca inicjalizacja: T obj = arg; – wymaga konwersji na prvalue.

    Przykłady błędów:

    
    int& r = 42;    // Błąd: prvalue nie może bindować do lvalue-reference
    const int& cr = 42; // Poprawnie: wydłużenie życia prvalue
    

    Zaawansowane scenariusze

    Materializacja prvalue

    Standard C++17 wprowadził zasadę, że prvalue jest materializowane (staje się xvalue) w kontekstach wymagających obiektu:

    • inicjalizacja referencji,
    • dostęp do składowych,
    • operatory logiczne.

    Przykład:

    
    int* p = &(std::string("temp").length()); // Materializacja tymczasowego stringa
    

    Kategorie w wyrażeniach lambda

    Domyślne przechwytywanie zmiennych ([=], [&]) różnicuje kategorie:

    
    int x = 10;
    auto lambda = [y = x + 1] { … }; // y jest prvalue
    auto lambda2 = [&] { return x; }; // x jest lvalue
    

    SFINAE a kategorie

    Szablony mogą wykorzystywać kategorie do dopasowania przeciążeń:

    
    template<typename T> void f(T&);   // T: lvalue
    template<typename T> void f(T&&); // T: rvalue
    

    Podsumowanie

    System kategorii wartości w C++ ewoluował od prostego podziału lvalue/rvalue do wyrafinowanego modelu pięciu kategorii, umożliwiającego zaawansowane mechanizmy optymalizacji. Zrozumienie różnic między lvalue, prvalue i xvalue jest kluczowe dla:

    • efektywnego wykorzystania semantyki przenoszenia;
    • poprawnego stosowania doskonałego przekazywania;
    • unikania błędów przy pracy z referencjami i tymczasowymi obiektami.

    Przyszłe standardy mogą rozszerzyć ten model o nowe koncepcje (np. pvalue z propozycji P0847), jednak obecna implementacja stanowi fundament bezpieczeństwa i wydajności nowoczesnego kodu C++.

    Polecane:

    • Standardowe konwersje wyrażeń a kategorie wartości w programowaniu C++
    • Referencje uniwersalne i std::forward – zarządzanie zasobami
    • Zaawansowane scenariusze z std::visit i wieloma wariantami
    • Historia wyrażeń lambda w C++ od C++03 do C++20
    • Wyszukiwanie testów w Google Test – metody i narzędzia
    Share. Facebook Twitter LinkedIn Email Copy Link
    Oskar Klimkiewicz
    • Website

    Inżynier oprogramowania specjalizujący się w C++, absolwent Wydziału Elektroniki i Technik Informacyjnych Politechniki Warszawskiej. Od ponad 8 lat projektuje i rozwija systemy o wysokiej dostępności, głównie dla branży fintech i IoT. PS. Zdjęcie wyretuszowane przez AI :)

    Podobne artykuły

    Maszyna stanów oparta o std::variant

    8 Mins Read

    Tablice w C++ od podstaw – deklaracja, inicjalizacja, iteracja i typowe pułapki

    4 Mins Read

    std::deque w C++ – kiedy wybrać dwukierunkową kolejkę zamiast vectora

    4 Mins Read
    Leave A Reply Cancel Reply

    Oglądaj, słuchaj, ćwicz - zdobywaj nowe umiejętności online
    Nie przegap

    Opera Portable – przeglądarka internetowa na pendrive bez instalacji

    Oskar Klimkiewicz4 Mins Read

    W erze mobilności i pracy zdalnej Opera Portable staje się nieocenionym narzędziem dla użytkowników, którzy…

    doPDF – wirtualna drukarka do konwersji dokumentów na PDF

    2026-03-08

    Kaspersky Free – podstawowa ochrona antywirusowa za darmo

    2026-03-07

    PeaZip – darmowy program do otwierania archiwów ZIP i RAR

    2026-03-05
    Social media
    • Facebook
    • Twitter
    • LinkedIn
    O nas
    O nas

    CPP Polska to serwis internetowy poświęcony technologii, programowaniu, IT, biznesowi i finansom. Znajdziesz tu porady, wskazówki i instrukcje dla wszystkich czytelników IT & Tech & Biz.

    Facebook X (Twitter) LinkedIn RSS
    Najnowsze

    Opera Portable – przeglądarka internetowa na pendrive bez instalacji

    2026-03-09

    doPDF – wirtualna drukarka do konwersji dokumentów na PDF

    2026-03-08

    Kaspersky Free – podstawowa ochrona antywirusowa za darmo

    2026-03-07
    Popularne

    Skrajnie niepotrzebne, skrajne przypadki w C++

    2025-06-28

    Wyszukiwanie testów w Google Test – metody i narzędzia

    2025-06-28

    Czy C jest wolniejszy od C++? Zero-cost abstraction w praktyce

    2025-06-28
    © 2026 CPP Polska. Wszelkie prawa zastrzeżone.
    • Lista publikacji
    • Współpraca
    • Kontakt

    Type above and press Enter to search. Press Esc to cancel.