Value categories ================ - každý výraz v C++ je charakterizován dvěma nezávislými vlastnostmi: "typem" a "value category" - každý výraz má nějaký typ a spadá právě do jedné z primárních value categories: 1. lvalue historický název - mohou se vyskytovat nalevo od přiřazovacího operátoru např. jméno proměnné, výrazy jako "a", "a = b", "a += b", "++a", "*p", atd. vlastnosti: - identifikují nějaký objekt, lze získat jeho adresu (např. "&++a") - mohou se vyskytovat nalevo od přiřazovacího operátoru (pokud daný objekt není "const") 2. prvalue ("pure" rvalue) výrazy jejichž vyhodnocení počítá nějakou hodnotu a/nebo inicializuje nějaký objekt (lvalue nebo xvalue) např. "42", "true", "a + b", "a++", "&a" (adresa nějakého objektu) atd. vlastnosti: - nelze získat adresu - nelze použít nalevo od přiřazovacího operátoru 3. xvalue ("expiring" value) - podobně jako lvalue odkazuje na nějaký objekt, který je ale typicky na konci své životnosti (díky této kategorii lze prodloužit životnost dočasných objektů pomocí tzv. "rvalue reference" - viz níže) - od standardu C++17 sem patří všechny dočasné objekty (před tím patřily do prvalue) -- ale výrazy které inicializují dočasné objekty jsou stále prvalues (provede se implicitní konverze prvalue -> xvalue) např. "a.m", kde "a" je prvalue (instance nějaké třídy) "funkce()", kde funkce vrací "rvalue reference" (viz níže) vlastnosti: - nelze získat adresu - nelze použít nalevo od přiřazovacího operátoru - dále existují smíšené kategorie: glvalue ("generalized" lvalue): lvalue nebo xvalue -> kategorie výrazů, které mají identitu (identifikují nějaký objekt) - glvalue je možné implicitně převést na prvalue rvalue: prvalue nebo xvalue -> kategorie výrazů, které lze přesunout ("move") pomocí "rvalue reference" (&&) - další vlastnosti omezující použití různých výrazů: - bindování referencí (viz níže) - abstraktní a polymorfní třídy - neúplné typy (šablony) - bindování referencí - lvalue reference (tj. např. "int& a = b") lze inicializovat pomocí: lvalue - const lvalue reference (tj. např. "const int& a = b") lze inicializovat pomocí: lvalue, rvalue při inicializaci pomocí rvalue dojde k prodloužení životnosti daného objektu - rvalue reference (tj. např. "int&& a = b") lze inicializovat pomocí: rvalue při inicializaci dojde k prodloužení životnosti daného objektu pomocí rvalue reference lze modifikovat dočasné objekty - viz "move constructor", "move assignment" Reference --------- 1. https://en.cppreference.com/w/cpp/language/value_category 2. https://akrzemi1.wordpress.com/2012/02/03/value-semantics/ 3. https://stackoverflow.com/questions/5481539/what-does-t-double-ampersand-mean-in-c11