Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Reference initialization

      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
      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
       
       

      Binds a reference to an object.

      Contents

      [edit]Syntax

      [edit]Non-list-initialization
      T &ref=target;

      T &ref(target);

      (1)
      T &&ref=target;

      T &&ref(target);

      (2)(since C++11)
      func-refpar(target) (3)
      returntarget; (4)(inside the definition offunc-refret )
      Class::Class(...) :ref-member(target) { ...} (5)(inside the definition ofClass )
      [edit]Ordinary list-initialization(since C++11)
      T &ref= {arg1,arg2, ...};

      T &ref{arg1,arg2, ...};

      (1)
      T &&ref= {arg1,arg2, ...};

      T &&ref{arg1,arg2, ...};

      (2)
      func-refpar({arg1,arg2, ...}); (3)
      [edit]Designated list-initialization(since C++20)
      T &ref= {.des1=arg1, .des2{arg2} ...};

      T &ref{.des1=arg1, .des2{arg2} ...};

      (1)
      T &&ref= {.des1=arg1, .des2{arg2} ...};

      T &&ref{.des1=arg1, .des2{arg2} ...};

      (2)
      func-refpar({.des1=arg1, .des2{arg2} ...}); (3)

      A reference toT can be initialized with an object of typeT, a function of typeT, or an object implicitly convertible toT. Once initialized, a reference cannot be reseated (changed) to refer to another object.

      References are initialized in the following situations:

      1) When a namedlvalue reference variable is declared with an initializer.
      2) When a namedrvalue reference variable is declared with an initializer.
      3) In a function call expression, when the function parameter has reference type.
      4) In thereturn statement, when the function returns a reference type.The program is ill-formed if the returned reference is bound to the result of atemporary expression.(since C++26)
      5) When anon-static data member of reference type is initialized using amember initializer.

      [edit]Explanation

      T - the referenced type
      ref - the reference variable to be initialized
      target - the initializer expression being used
      func-refpar - a function with a parameter of reference type (T & orT &&(since C++11))
      func-refret - a function whose returns type is a reference type (T & orT &&(since C++11))
      Class - a class name
      ref-member - a non-static data member of reference type (T & orT &&(since C++11)) ofClass
      des1,des2, ... - designators
      arg1,arg2, ... - the initializers in initializer lists

      [edit]Definitions

      For two typesT1 andT2:

      • Given the cv-unqualified versions ofT1 andT2 asU1 andU2 respectively, ifU1 issimilar toU2, orU1 is abase class ofU2,T1 isreference-related toT2.
      • If a prvalue of type “pointer toT2” can be converted to the type “pointer toT1” via a standard conversion sequence,T1 isreference-compatible withT2.

      [edit]Initialization rules

      If a reference initialization uses an ordinary or designated(since C++20) list-initialization, the rules oflist-initialization are followed.

      (since C++11)

      For non-list reference initialization, given the type oftarget asU, the reference eitherbinds directly totarget or binds to a value of typeT converted fromtarget. Direct binding is considered first, followed by indirect binding, if neither binding is available, the program is ill-formed.

      In all cases where the reference-compatible relationship of two types is used to establish the validity of a reference binding and the standard conversion sequence would be ill-formed, a program that necessitates such a binding is ill-formed.

      [edit]Direct binding

      If all following conditions are satisfied:

      • The reference to be initialized is an lvalue reference.
      • target is a non-bit-field lvalue.
      • T is reference-compatible withU.

      Then the reference binds totarget, or to its appropriate base class subobject:

      double d=2.0;double& rd= d;// rd refers to dconstdouble& rcd= d;// rcd refers to d struct A{};struct B: A{} b; A& ra= b;// ra refers to A subobject in bconst A& rca= b;// rca refers to A subobject in b

      Otherwise, if all following conditions are satisfied:

      • The reference to be initialized is an lvalue reference.
      • U is a class type.
      • T is not reference-related toU.
      • target can be converted to an lvalue of typeV such thatT is reference-compatible withV.

      Then the reference binds to the lvalue result of the conversion, or to its appropriate base class subobject:

      struct A{};struct B: A{ operatorint&();}; int& ir= B();// ir refers to the result of B::operator int&

      Otherwise, if the reference to be initialized is an lvalue reference, andT is not const-qualified or is volatile-qualified, the prorgram is ill-formed:

      double& rd2=2.0;// error: not an lvalue and reference is not constint i=2;double& rd3= i;// error: type mismatch and reference is not const

      Otherwise, if all following conditions are satisfied:

      • target is a value of any following category:
      • rvalue
      (until C++11)
      • non-bit-field xvalue
      • class prvalue
      • array prvalue
      • function lvalue
      (since C++11)
      (until C++17)
      • non-bit-field rvalue
      • function lvalue
      (since C++17)
      • T is reference-compatible withU.

      Then the reference binds totarget, or to its appropriate base class subobject:

      struct A{};struct B: A{};extern B f(); const A& rca2= f();// bound to the A subobject of the B rvalue.A&& rra= f();// same as above int i2=42;int&& rri=static_cast<int&&>(i2);// bound directly to i2

      Iftarget is a prvalue,temporary materialization is applied to it, considering the type of the prvalue to be the adjusted typeP.

      • P isadjusted from the type oftarget (i.e.U) by adding the cv-qualification ofT to it.

      In this case, the reference binds to the result object, or to its appropriate base class subobject.

      (since C++17)

      Otherwise, if all following conditions are satisfied:

      • U is a class type.
      • T is not reference-related toU.
      • target can be converted to a valuev of typeV such thatT is reference-compatible withV, wherev is of any following category:
      • rvalue
      (until C++11)
      • xvalue
      • class prvalue
      • function lvalue
      (since C++11)
      (until C++17)
      • rvalue
      • function lvalue
      (since C++17)

      Then the reference binds to the result of the conversion, or to its appropriate base class subobject:

      struct A{};struct B: A{};struct X{ operator B();} x; const A& r= x;// bound to the A subobject of the result of the conversionB&& rrb= x;// bound directly to the result of the conversion

      If the result of the conversion is a prvalue,temporary materialization is applied to it, considering the type of the prvalue to be the adjusted typeP.

      • P isadjusted from the type of the conversion result by adding the cv-qualification ofT to it.

      In this case, the reference binds to the result object, or to its appropriate base class subobject.

      (since C++17)

      [edit]Indirect binding

      If direct binding is not available, indirect binding is considered. In this case,T cannot be reference-related toU.

      IfT orU is a class type, user-defined conversions are considered using the rules forcopy-initialization of an object of typeT by user-defined conversion. The program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed. The result of the call to the conversion function, as described for the non-referencecopy-initialization, is then used to direct-initialize the reference. For this direct-initialization, user-defined conversions are not considered.

      Otherwise, a temporary of typeT is created and copy-initialized fromtarget. The reference is then bound to the temporary.

      (until C++17)

      Otherwise,target is implicitly converted to a prvalue of type “cv-unqualifiedT”. The temporary materialization conversion is applied, considering the type of the prvalue to beT, and the reference is bound to the result object.

      (since C++17)
      conststd::string& rs="abc";// rs refers to temporary copy-initialized from char arrayconstdouble& rcd2=2;// rcd2 refers to temporary with value 2.0int i3=2;double&& rrd3= i3;// rrd3 refers to temporary with value 2.0

      [edit]Lifetime of a temporary

      Whenever a reference is bound to a temporary object or to a subobject thereof, the lifetime of the temporary object is extended to match the lifetime of the reference (checktemporary object lifetime exceptions), where the temporary object or its subobject is denoted by one of following expression:

      • aprvalue expression of an object type,
      (until C++17)
      (since C++17)

      There are following exceptions to this lifetime rule:

      • a temporary bound to a return value of a function in areturn statement is not extended: it is destroyed immediately at the end of the return expression. Suchreturn statement always returns a dangling reference.
      (until C++26)
      • a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.
      • a temporary bound to a reference in the initializer used in a new-expression exists until the end of the full expression containing that new-expression, not as long as the initialized object. If the initialized object outlives the full expression, its reference member becomes a dangling reference.
      (since C++11)
      • a temporary bound to a reference in a reference element of an aggregate initialized usingdirect-initialization syntax(parentheses) exists until the end of the full expression containing the initializer, as opposed tolist-initialization syntax{braces}.
      struct A{int&& r;}; A a1{7};// OK, lifetime is extendedA a2(7);// well-formed, but dangling reference
      (since C++20)

      In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference variable or data member to which the temporary was bound, does not affect its lifetime.

      [edit]Notes

      References appear without initializers only in function parameter declaration, in function return type declaration, in the declaration of a class member, and with theextern specifier.

      Until the resolution ofCWG issue 1696, a temporary is permitted to bound to a reference member in a constructorinitializer list, and it persists only until the constructor exits, not as long as the object exists. Such initialization is ill-formed sinceCWG 1696, although many compilers still support it (a notable exception is clang).

      [edit]Example

      Run this code
      #include <sstream>#include <utility> struct S{int mi;conststd::pair<int,int>& mp;// reference member}; void foo(int){} struct A{}; struct B: A{int n;    operatorint&(){return n;}}; B bar(){return B();} //int& bad_r;      // error: no initializerexternint& ext_r;// OK int main(){//  Lvaluesint n=1;int& r1= n;// lvalue reference to the object nconstint& cr(n);// reference can be more cv-qualifiedvolatileint& cv{n};// any initializer syntax can be usedint& r2= r1;// another lvalue reference to the object n//  int& bad = cr;                  // error: less cv-qualifiedint& r3=const_cast<int&>(cr);// const_cast is needed void(&rf)(int)= foo;// lvalue reference to functionint ar[3];int(&ra)[3]= ar;// lvalue reference to array     B b;    A& base_ref= b;// reference to base subobjectint& converted_ref= b;// reference to the result of a conversion //  Rvalues//  int& bad = 1;        // error: cannot bind lvalue ref to rvalueconstint& cref=1;// bound to rvalueint&& rref=1;// bound to rvalue const A& cref2= bar();// reference to A subobject of B temporary    A&& rref2= bar();// same int&& xref=static_cast<int&&>(n);// bind directly to n//  int&& copy_ref = n;                 // error: can't bind to an lvaluedouble&& copy_ref= n;// bind to an rvalue temporary with value 1.0 //  Restrictions on temporary lifetimes//  std::ostream& buf_ref = std::ostringstream() << 'a';// the ostringstream temporary was bound to the left operand// of operator<< but its lifetime ended at the semicolon so// the buf_ref is a dangling reference     S a{1,{2,3}};// temporary pair {2, 3} bound to the reference member// a.mp and its lifetime is extended to match// the lifetime of object a     S* p= new S{1,{2,3}};// temporary pair {2, 3} bound to the reference// member p->mp, but its lifetime ended at the semicolon// p->mp is a dangling reference    delete p; // Imitate [[maybe_unused]] applied to the following variables:[](...){}(        cv, r2, r3, rf, ra, base_ref, converted_ref,        a, cref, rref, cref2, rref2, copy_ref, xref);}

      [edit]Defect reports

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

      DRApplied toBehavior as publishedCorrect behavior
      CWG 391C++98initialize a reference to const-qualified type with a class type
      rvalue might create a temporary, and a constructor of that class
      was required in order to copy the rvalue into that temporary
      no temporary is
      created, constructor
      is not required
      CWG 450C++98a reference to const-qualified array could not be
      initialized with a reference-compatible array rvalue
      allowed
      CWG 589C++98a reference could not bind directly to an array or class rvalueallowed
      CWG 656C++98a reference to const-qualified type initialized with a type which is not
      reference-compatible but has a conversion function to a reference-
      compatible type was bound to a temporary copied from the return
      value (or its base class subobject) of the conversion function
      bound to the return
      value (or its base class
      subobject) directly
      CWG 1287C++11the conversion fromtarget of class type to another
      reference-compatible type could only be implicit
      allow explicit
      conversions
      CWG 1295C++11a reference could bind to a bit-field xvalueprohibited
      CWG 1299C++98the definition of temporary was unclearmade clear
      CWG 1571C++98user-defined conversions in indirect
      binding did not consider the type oftarget
      considered
      CWG 1604C++98user-defined conversions were not considered in indirect bindingconsidered
      CWG 2352C++98reference compatibility did not consider qualification conversionsconsidered
      CWG 2481C++17cv-qualification was not added to the result type
      of temporary materialization in indirect binding
      added
      CWG 2657C++17cv-qualification was not added to the result type
      of temporary materialization in direct binding
      added
      CWG 2801C++98reference-related types were allowed for indirect bindingprohibited

      [edit]See also

      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/reference_initialization&oldid=171898"

      [8]ページ先頭

      ©2009-2025 Movatter.jp