Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Value categories

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Value categories
      Order of evaluation
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
      Expressions
      General
      Literals
      Operators
      Conversions
       

      Each C++expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: atype and avalue category. Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories:prvalue,xvalue, andlvalue.

      • aglvalue (“generalized” lvalue) is an expression whose evaluation determines the identity of an object or function;
      • aprvalue (“pure” rvalue) is an expression whose evaluation
      • computes the value of an operand of a built-in operator (such prvalue has noresult object), or
      • initializes an object (such prvalue is said to have aresult object).
      The result object may be a variable, an object created bynew-expression, a temporary created bytemporary materialization, or a member thereof. Note that non-voiddiscarded expressions have a result object (the materialized temporary). Also, every class and array prvalue has a result object except when it is the operand ofdecltype;
      • anxvalue (an “eXpiring” value) is a glvalue that denotes an object whose resources can be reused;
      • anlvalue is a glvalue that is not an xvalue;
      Extended content

      So-called, historically, because lvalues could appear on the left-hand side of an assignment expression. In general, it's not always the case:

      void foo(); void baz(){int a;// Expression `a` is lvalue    a=4;// OK, could appear on the left-hand side of an assignment expression int&b{a};// Expression `b` is lvalue    b=5;// OK, could appear on the left-hand side of an assignment expression constint&c{a};// Expression `c` is lvalue    c=6;// ill-formed, assignment of read-only reference // Expression `foo` is lvalue// address may be taken by built-in address-of operatorvoid(*p)()=&foo;     foo= baz;// ill-formed, assignment of function}
      • anrvalue is a prvalue or an xvalue;
      Extended content

      So-called, historically, because rvalues could appear on the right-hand side of an assignment expression. In general, it's not always the case:

      Run this code
      #include <iostream> struct S{    S(): m{42}{}    S(int a): m{a}{}int m;}; int main(){    S s; // Expression `S{}` is prvalue// May appear on the right-hand side of an assignment expression    s= S{}; std::cout<< s.m<<'\n'; // Expression `S{}` is prvalue// Can be used on the left-hand side toostd::cout<<(S{}= S{7}).m<<'\n';}

      Output:

      427

      Note: this taxonomy went through significant changes with past C++ standard revisions, seeHistory below for details.

      Extended content

      Despite their names, these terms classify expressions, not values.

      Run this code
      #include <type_traits>#include <utility> template<class T>struct is_prvalue:std::true_type{};template<class T>struct is_prvalue<T&>:std::false_type{};template<class T>struct is_prvalue<T&&>:std::false_type{}; template<class T>struct is_lvalue:std::false_type{};template<class T>struct is_lvalue<T&>:std::true_type{};template<class T>struct is_lvalue<T&&>:std::false_type{}; template<class T>struct is_xvalue:std::false_type{};template<class T>struct is_xvalue<T&>:std::false_type{};template<class T>struct is_xvalue<T&&>:std::true_type{}; int main(){int a{42};int& b{a};int&& r{std::move(a)}; // Expression `42` is prvalue    static_assert(is_prvalue<decltype((42))>::value); // Expression `a` is lvalue    static_assert(is_lvalue<decltype((a))>::value); // Expression `b` is lvalue    static_assert(is_lvalue<decltype((b))>::value); // Expression `std::move(a)` is xvalue    static_assert(is_xvalue<decltype((std::move(a)))>::value); // Type of variable `r` is rvalue reference    static_assert(std::is_rvalue_reference<decltype(r)>::value); // Type of variable `b` is lvalue reference    static_assert(std::is_lvalue_reference<decltype(b)>::value); // Expression `r` is lvalue    static_assert(is_lvalue<decltype((r))>::value);}

      Contents

      [edit]Primary categories

      [edit]lvalue

      The following expressions arelvalue expressions:

      Extended content
      void foo(){} void baz(){// `foo` is lvalue// address may be taken by built-in address-of operatorvoid(*p)()=&foo;}
      struct foo{}; template<foo a>void baz(){const foo* obj=&a;// `a` is an lvalue, template parameter object}
      • a function call or an overloaded operator expression, whose return type is lvalue reference, such asstd::getline(std::cin, str),std::cout<<1,str1= str2, or++it;
      Extended content
      int& a_ref(){staticint a{3};return a;} void foo(){    a_ref()=5;// `a_ref()` is lvalue, function call whose return type is lvalue reference}
      Extended content
      struct foo{enum bar{        m// member enumerator};}; void baz(){    foo a;    a.m=42;// ill-formed, lvalue required as left operand of assignment}
      struct foo{void m(){}// non-static member function}; void baz(){    foo a; // `a.m` is a prvalue, hence the address cannot be taken by built-in// address-of operatorvoid(foo::*p1)()=&a.m;// ill-formed void(foo::*p2)()=&foo::m;// OK: pointer to member function}
      struct foo{staticvoid m(){}// static member function}; void baz(){    foo a;void(*p1)()=&a.m;// `a.m` is an lvaluevoid(*p2)()=&foo::m;// the same}
      • p->m, the built-inmember of pointer expression, except wherem is a member enumerator or a non-static member function;
      • a.*mp, thepointer to member of object expression, wherea is an lvalue andmp is a pointer to data member;
      • p->*mp, the built-inpointer to member of pointer expression, wheremp is a pointer to data member;
      • a, b, the built-incomma expression, whereb is an lvalue;
      • a? b: c, theternary conditional expression for certainb andc (e.g., when both are lvalues of the same type, but seedefinition for detail);
      • astring literal, such as"Hello, world!";
      • a cast expression to lvalue reference type, such asstatic_cast<int&>(x) orstatic_cast<void(&)(int)>(x);
      • a constanttemplate parameter of an lvalue reference type;
      template<int& v>void set(){    v=5;// template parameter is lvalue} int a{3};// static variable, fixed address is known at compile-time void foo(){    set<a>();}
      • a function call or an overloaded operator expression, whose return type is rvalue reference to function;
      • a cast expression to rvalue reference to function type, such asstatic_cast<void(&&)(int)>(x).
      (since C++11)

      Properties:

      • Same asglvalue (below).
      • Address of an lvalue may be taken by built-in address-of operator:&++i[1] and&std::hex are valid expressions.
      • A modifiable lvalue may be used as the left-hand operand of the built-in assignment and compound assignment operators.
      • An lvalue may be used toinitialize an lvalue reference; this associates a new name with the object identified by the expression.

      [edit]prvalue

      The following expressions areprvalue expressions:

      template<int v>void foo(){// not an lvalue, `v` is a template parameter of scalar type intconstint* a=&v;// ill-formed     v=3;// ill-formed: lvalue required as left operand of assignment}
      (since C++11)
      (since C++20)

      Properties:

      • Same asrvalue (below).
      • A prvalue cannot bepolymorphic: thedynamic type of the object it denotes is always the type of the expression.
      • A non-class non-array prvalue cannot becv-qualified, unless it ismaterialized in order to bebound to a reference to a cv-qualified type(since C++17). (Note: a function call or cast expression may result in a prvalue of non-class cv-qualified type, but the cv-qualifier is generally immediately stripped out.)
      • A prvalue cannot haveincomplete type (except for typevoid, see below, or when used indecltype specifier).
      • A prvalue cannot haveabstract class type or an array thereof.

      [edit]xvalue

      The following expressions arexvalue expressions:

      • a function call or an overloaded operator expression, whose return type is rvalue reference to object, such asstd::move(x);
      • a[n], the built-insubscript expression, where one operand is an array rvalue;
      • a cast expression to rvalue reference to object type, such asstatic_cast<char&&>(x);
      (since C++11)
      (since C++17)
      (since C++23)

      Properties:

      • Same as rvalue (below).
      • Same as glvalue (below).

      In particular, like all rvalues, xvalues bind to rvalue references, and like all glvalues, xvalues may bepolymorphic, and non-class xvalues may becv-qualified.

      Extended content
      Run this code
      #include <type_traits> template<class T>struct is_prvalue:std::true_type{};template<class T>struct is_prvalue<T&>:std::false_type{};template<class T>struct is_prvalue<T&&>:std::false_type{}; template<class T>struct is_lvalue:std::false_type{};template<class T>struct is_lvalue<T&>:std::true_type{};template<class T>struct is_lvalue<T&&>:std::false_type{}; template<class T>struct is_xvalue:std::false_type{};template<class T>struct is_xvalue<T&>:std::false_type{};template<class T>struct is_xvalue<T&&>:std::true_type{}; // Example from C++23 standard: 7.2.1 Value category [basic.lval]struct A{int m;}; A&& operator+(A, A);A&& f(); int main(){    A a;    A&& ar=static_cast<A&&>(a); // Function call with return type rvalue reference is xvalue    static_assert(is_xvalue<decltype((f()))>::value); // Member of object expression, object is xvalue, `m` is a non-static data member    static_assert(is_xvalue<decltype((f().m))>::value); // A cast expression to rvalue reference    static_assert(is_xvalue<decltype((static_cast<A&&>(a)))>::value); // Operator expression, whose return type is rvalue reference to object    static_assert(is_xvalue<decltype((a+ a))>::value); // Expression `ar` is lvalue, `&ar` is valid    static_assert(is_lvalue<decltype((ar))>::value);[[maybe_unused]] A* ap=&ar;}

      [edit]Mixed categories

      [edit]glvalue

      Aglvalue expression is either lvalue or xvalue.

      Properties:

      • A glvalue may be implicitly converted to a prvalue with lvalue-to-rvalue, array-to-pointer, or function-to-pointerimplicit conversion.
      • A glvalue may bepolymorphic: thedynamic type of the object it identifies is not necessarily the static type of the expression.
      • A glvalue can haveincomplete type, where permitted by the expression.

      [edit]rvalue

      Anrvalue expression is either prvalue or xvalue.

      Properties:

      • Address of an rvalue cannot be taken by built-in address-of operator:&int(),&i++[3],&42, and&std::move(x) are invalid.
      • An rvalue can't be used as the left-hand operand of the built-in assignment or compound assignment operators.
      • An rvalue may be used toinitialize a const lvalue reference, in which case the lifetime of the temporary object identified by the rvalue isextended until the scope of the reference ends.
      • An rvalue may be used toinitialize an rvalue reference, in which case the lifetime of the temporary object identified by the rvalue isextended until the scope of the reference ends.
      • When used as a function argument and whentwo overloads of the function are available, one taking rvalue reference parameter and the other taking lvalue reference to const parameter, an rvalue binds to the rvalue reference overload (thus, if both copy and move constructors are available, an rvalue argument invokes themove constructor, and likewise with copy and move assignment operators).
      (since C++11)

      [edit]Special categories

      [edit]Pending member function call

      The expressionsa.mf andp->mf, wheremf is anon-static member function, and the expressionsa.*pmf andp->*pmf, wherepmf is apointer to member function, are classified as prvalue expressions, but they cannot be used to initialize references, as function arguments, or for any purpose at all, except as the left-hand argument of the function call operator, e.g.(p->*pmf)(args).

      [edit]Void expressions

      Function call expressions returningvoid, cast expressions tovoid, andthrow-expressions are classified as prvalue expressions, but they cannot be used to initialize references or as function arguments. They can be used in discarded-value contexts (e.g. on a line of its own, as the left-hand operand of the comma operator, etc.) and in thereturn statement in a function returningvoid. In addition, throw-expressions may be used as the second and the third operands of theconditional operator ?:.

      Void expressions have noresult object.

      (since C++17)

      [edit]Bit-fields

      An expression that designates abit-field (e.g.a.m, wherea is an lvalue of typestruct A{int m:3;}) is a glvalue expression: it may be used as the left-hand operand of the assignment operator, but its address cannot be taken and a non-const lvalue reference cannot be bound to it. A const lvalue reference or rvalue reference can be initialized from a bit-field glvalue, but a temporary copy of the bit-field will be made: it won't bind to the bit-field directly.

      Move-eligible expressions

      Although an expression consisting of the name of any variable is an lvalue expression, such expression may be move-eligible if it appears as the operand of

      If an expression is move-eligible, it is treatedeither as an rvalue or as an lvalue(until C++23)as an rvalue(since C++23) for the purpose ofoverload resolution (thus it may select themove constructor). SeeAutomatic move from local variables and parameters for details.

      (since C++11)

      [edit]History

      [edit]CPL

      The programming languageCPL was first to introduce value categories for expressions: all CPL expressions can be evaluated in "right-hand mode", but only certain kinds of expression are meaningful in "left-hand mode". When evaluated in right-hand mode, an expression is regarded as being a rule for the computation of a value (the right-hand value, orrvalue). When evaluated in left-hand mode an expression effectively gives an address (the left-hand value, orlvalue). "Left" and "Right" here stood for "left of assignment" and "right of assignment".

      [edit]C

      The C programming language followed a similar taxonomy, except that the role of assignment was no longer significant: C expressions are categorized between "lvalue expressions" and others (functions and non-object values), where "lvalue" means an expression that identifies an object, a "locator value"[4].

      [edit]C++98

      Pre-2011 C++ followed the C model, but restored the name "rvalue" to non-lvalue expressions, made functions into lvalues, and added the rule that references can bind to lvalues, but only references to const can bind to rvalues. Several non-lvalue C expressions became lvalue expressions in C++.

      [edit]C++11

      With the introduction of move semantics in C++11, value categories were redefined to characterize two independent properties of expressions[5]:

      • has identity: it's possible to determine whether the expression refers to the same entity as another expression, such as by comparing addresses of the objects or the functions they identify (obtained directly or indirectly);
      • can be moved from:move constructor,move assignment operator, or another function overload that implements move semantics can bind to the expression.

      In C++11, expressions that:

      • have identity and cannot be moved from are calledlvalue expressions;
      • have identity and can be moved from are calledxvalue expressions;
      • do not have identity and can be moved from are calledprvalue ("pure rvalue") expressions;
      • do not have identity and cannot be moved from are not used[6].

      The expressions that have identity are called "glvalue expressions" (glvalue stands for "generalized lvalue"). Both lvalues and xvalues are glvalue expressions.

      The expressions that can be moved from are called "rvalue expressions". Both prvalues and xvalues are rvalue expressions.

      [edit]C++17

      In C++17,copy elision was made mandatory in some situations, and that required separation of prvalue expressions from the temporary objects initialized by them, resulting in the system we have today. Note that, in contrast with the C++11 scheme, prvalues are no longer moved from.

      [edit]Footnotes

      1. Assumingi has built-in type or the pre-increment operator isoverloaded to return by lvalue reference.
      2. 2.02.12.22.3Special rvalue category, seepending member function call.
      3. Assumingi has built-in type or the post-increment operator is notoverloaded to return by lvalue reference.
      4. "A difference of opinion within the C community centered around the meaning of lvalue, one group considering an lvalue to be any kind of object locator, another group holding that an lvalue is meaningful on the left side of an assigning operator. The C89 Committee adopted the definition of lvalue as an object locator." -- ANSI C Rationale, 6.3.2.1/10.
      5. "New" Value Terminology by Bjarne Stroustrup, 2010.
      6. const prvalues (only allowed for class types) and const xvalues do not bind toT&& overloads, but they bind to theconst T&& overloads, which are also classified as "move constructor" and "move assignment operator" by the standard, satisfying the definition of "can be moved from" for the purpose of this classification. However, such overloads cannot modify their arguments and are not used in practice; in their absence const prvalues and const xvalues bind toconst T& overloads.

      [edit]References

      • C++23 standard (ISO/IEC 14882:2024):
      • 7.2.1 Value category [basic.lval]
      • C++20 standard (ISO/IEC 14882:2020):
      • 7.2.1 Value category [basic.lval]
      • C++17 standard (ISO/IEC 14882:2017):
      • 6.10 Lvalues and rvalues [basic.lval]
      • C++14 standard (ISO/IEC 14882:2014):
      • 3.10 Lvalues and rvalues [basic.lval]
      • C++11 standard (ISO/IEC 14882:2011):
      • 3.10 Lvalues and rvalues [basic.lval]
      • C++98 standard (ISO/IEC 14882:1998):
      • 3.10 Lvalues and rvalues [basic.lval]

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 616C++11member access and member access through
      pointer to member of an rvalue resulted in prvalue
      reclassified as xvalue
      CWG 1059C++11array prvalues could not be cv-qualifiedallowed
      CWG 1213C++11subscripting an array rvalue resulted in lvaluereclassified as xvalue

      [edit]See also

      C documentation forvalue categories

      [edit]External links

      1. C++ value categories and decltype demystified — David Mazières, 2021
      2. Empirically determine value category of expression — StackOverflow
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/value_category&oldid=182814"

      [8]ページ先頭

      ©2009-2025 Movatter.jp