Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      List-initialization(since C++11)

      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
       
       

      Initializes an object from abrace-enclosed initializer list.

      Contents

      [edit]Syntax

      [edit]Direct-list-initialization

      T object{arg1, arg2, ...};

      T object{.des1=arg1, .des2{arg2}...};

      (since C++20)
      (1)
      T{arg1, arg2, ...}

      T{.des1=arg1, .des2{arg2}...}

      (since C++20)
      (2)
      newT{arg1, arg2, ...}

      newT{.des1=arg1, .des2{arg2}...}

      (since C++20)
      (3)
      Class{T member{arg1, arg2, ...}; };

      Class{T member{.des1=arg1, .des2{arg2}...}; };

      (since C++20)
      (4)
      Class::Class() :member{arg1, arg2, ...} {...

      Class::Class() :member{.des1=arg1, .des2{arg2}...} {...

      (since C++20)
      (5)

      [edit]Copy-list-initialization

      T object= {arg1, arg2, ...};

      T object= {.des1=arg1, .des2{arg2}...};

      (since C++20)
      (6)
      function({arg1, arg2, ...})

      function({.des1=arg1, .des2{arg2}...})

      (since C++20)
      (7)
      return {arg1, arg2, ...};

      return{.des1=arg1, .des2{arg2}...};

      (since C++20)
      (8)
      object[{arg1, arg2, ...}]

      object[{.des1=arg1, .des2{arg2}...}]

      (since C++20)
      (9)
      object= {arg1, arg2, ...}

      object= {.des1=arg1, .des2{arg2}...}

      (since C++20)
      (10)
      U({arg1, arg2, ...})

      U({.des1=arg1, .des2{arg2}...})

      (since C++20)
      (11)
      Class{T member= {arg1, arg2, ...}; };

      Class{T member= {.des1=arg1, .des2{arg2}...}; };

      (since C++20)
      (12)

      List initialization is performed in the following situations:

      • direct-list-initialization (both explicit and non-explicit constructors are considered)
      1) initialization of a named variable with a brace-enclosed initializer list
      2) initialization of an unnamed temporary with a brace-enclosed initializer list
      3) initialization of an object with dynamic storage duration with anew-expression, where the initializer is a brace-enclosed initializer list
      4) in a non-staticdata member initializer that does not use the equals sign
      5) in amember initializer list of a constructor if a brace-enclosed initializer list is used
      • copy-list-initialization (both explicit and non-explicit constructors are considered, but only non-explicit constructors may be called)
      6) initialization of a named variable with a brace-enclosed initializer list after an equals sign
      7) in a function call expression, with a brace-enclosed initializer list used as an argument and list-initialization initializes the function parameter
      8) in areturn statement with a brace-enclosed initializer list used as the return expression and list-initialization initializes the returned object
      9) in asubscript expression with a user-definedoperator[], where list-initialization initializes the parameter of the overloaded operator
      10) in anassignment expression, where list-initialization initializes the parameter of the overloaded operator
      11)functional cast expression or other constructor invocations, where a brace-enclosed initializer list is used in place of a constructor argument. Copy-list-initialization initializes the constructor's parameter (note; the typeU in this example is not the type that is being list-initialized;U's constructor's parameter is)
      12) in a non-staticdata member initializer that uses the equals sign

      [edit]Explanation

      The effects of list-initialization of an object of type (possibly cv-qualified)T are:

      • If the brace-enclosed initializer list contains adesignated initializer list andT is not a reference type,T must be an aggregate class. The ordered identifiers in the designators of the designated initializer list must form a subsequence of the ordered identifiers in the direct non-static data members ofT.Aggregate initialization is performed.
      (since C++20)
      • IfT is an aggregate class and the brace-enclosed initializer list, which does not contain a designated initializer list,(since C++20) has a single initializer clause of the same or derived type (possibly cv-qualified), the object is initialized from that initializer clause (bycopy-initialization for copy-list-initialization, or bydirect-initialization for direct-list-initialization).
      • Otherwise, ifT is a character array and the brace-enclosed initializer list has a single initializer clause that is an appropriately-typed string literal, the array isinitialized from the string literal as usual.
      • Otherwise, if the brace-enclosed initializer list is empty andT is a class type with a default constructor,value-initialization is performed.
      • Otherwise, ifT is a class type, the constructors ofT are considered, in two phases:
      • If the previous stage does not produce a match, all constructors ofT participate inoverload resolution against the set of arguments that consists of the initializer clauses of the brace-enclosed initializer list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).
      • Otherwise, ifT is anenumeration type that with fixed underlying typeU, the brace-enclosed initializer list has only one initializerv, and all following conditions are satisfied, then the enumeration is initialized with the result of convertingv toU:
        • The initialization is direct-list-initialization.
        • v is ofscalar type.
        • v is implicitly convertible toU.
        • The conversion fromv toU is non-narrowing.
      (since C++17)
      • Otherwise (ifT is not a class type), if the brace-enclosed initializer list has only one initializer clause and eitherT is not a reference type or is a reference type whose referenced type is same as or is a base class of the type of the initializer clause,T isdirect-initialized (in direct-list-initialization) orcopy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.
      • Otherwise, ifT is a reference type that is not compatible with the type of the initializer clause:
      • a prvalue temporary of the type referenced byT is copy-list-initialized, and the reference is bound to that temporary (this fails if the reference is a non-const lvalue reference).
      (until C++17)
      • a prvalue is generated. The prvalue initializes its result object by copy-list-initialization. The prvalue is then used to direct-initialize the reference (this fails if the reference is a non-const lvalue reference). The type of the temporary is the type referenced byT, unlessT is “reference to array of unknown bound ofU”, in which case the type of the temporary is the type ofx in the declarationU x[] H, whereH is the initializer list(since C++20).
      (since C++17)
      • Otherwise, if the brace-enclosed initializer list has no initializer clause,T isvalue-initialized.

      [edit]List-initializingstd::initializer_list

      An object of typestd::initializer_list<E> is constructed from an initializer list as if the compiler generated andmaterialized(since C++17) aprvalue of type “array ofNconst E”, whereN is the number of initializer clauses in the initializer list; this is called the initializer list’sbacking array.

      Each element of the backing array iscopy-initialized with the corresponding initializer clause of the initializer list, and thestd::initializer_list<E> object is constructed to refer to that array. A constructor or conversion function selected for the copy is required to beaccessible in the context of the initializer list. If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.

      The backing array has the same lifetime as any othertemporary object, except that initializing anstd::initializer_list object from the backing array extends the lifetime of the array exactly likebinding a reference to a temporary.

      void f(std::initializer_list<double> il); void g(float x){   f({1, x,3});} void h(){   f({1,2,3});} struct A{ mutableint i;}; void q(std::initializer_list<A>); void r(){    q({A{1}, A{2}, A{3}});} // The initialization above will be implemented in a way roughly equivalent to below,// assuming that the compiler can construct an initializer_list object with a pair of// pointers, and with the understanding that `__b` does not outlive the call to `f`. void g(float x){constdouble __a[3]={double{1},double{x},double{3}};// backing array    f(std::initializer_list<double>(__a, __a+3));} void h(){staticconstexprdouble __b[3]={double{1},double{2},double{3}};// backing array    f(std::initializer_list<double>(__b, __b+3));} void r(){const A __c[3]={A{1}, A{2}, A{3}};// backing array    q(std::initializer_list<A>(__c, __c+3));}

      Whether all backing arrays are distinct (that is, are stored innon-overlapping objects) is unspecified:

      bool fun(std::initializer_list<int> il1,std::initializer_list<int> il2){return il2.begin()== il1.begin()+1;} bool overlapping= fun({1,2,3},{2,3,4});// the result is unspecified:// the back arrays can share// storage within {1, 2, 3, 4}

      [edit]Narrowing conversions

      List-initialization limits the allowedimplicit conversions by prohibiting the following:

      • conversion from a floating-point type to an integer type
      • conversion from a floating-point typeT to another floating-point type whosefloating-point conversion rank is neither greater than nor equal to that ofT, except where the conversion result is aconstant expression and one of the following conditions is satisfied:
        • The converted value is finite, and the conversion does not overflow.
        • The values before and after the conversion are not finite.
      • conversion from an integer type to a floating-point type, except where the source is a constant expression whose value can be stored exactly in the target type
      • conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where
        • the source is abit-field whose widthw is less than that of its type (or, for anenumeration type, its underlying type) and the target type can represent all the values of a hypothetical extended integer type with widthw and with the same signedness as the original type, or
        • the source is a constant expression whose value can be stored exactly in the target type
      • conversion from a pointer type or pointer-to-member type tobool

      [edit]Notes

      Every initializer clause issequenced before any initializer clause that follows it in the brace-enclosed initializer list. This is in contrast with the arguments of afunction call expression, which areunsequenced(until C++17)indeterminately sequenced(since C++17).

      A brace-enclosed initializer list is not an expression and therefore has no type, e.g.decltype({1,2}) is ill-formed. Having no type implies that template type deduction cannot deduce a type that matches a brace-enclosed initializer list, so given the declarationtemplate<class T>void f(T); the expressionf({1,2,3}) is ill-formed. However, the template parameter can otherwise be deduced, as is the case forstd::vector<int> v(std::istream_iterator<int>(std::cin),{}), where the iterator type is deduced by the first argument but also used in the second parameter position. A special exception is made fortype deduction using the keywordauto, which deduces any brace-enclosed initializer list asstd::initializer_list in copy-list-initialization.

      Also because a brace-enclosed initializer list has no type,special rules for overload resolution apply when it is used as an argument to an overloaded function call.

      Aggregates copy/move initialize directly from brace-enclosed initializer list of a single initializer clause of the same type, but non-aggregates considerstd::initializer_list constructors first:

      struct X{};// aggregate struct Q// non-aggregate{    Q()=default;    Q(Qconst&)=default;    Q(std::initializer_list<Q>){}}; int main(){    X x;    X x2= X{x};// copy-constructor (not aggregate initialization)     Q q;    Q q2= Q{q};// initializer-list constructor (not copy constructor)}

      Some compilers (e.g., gcc 10) only consider conversion from a pointer or a pointer-to-member tobool narrowing in C++20 mode.

      Feature-test macroValueStdFeature
      __cpp_initializer_lists200806L(C++11)List-initialization andstd::initializer_list

      [edit]Example

      Run this code
      #include <iostream>#include <map>#include <string>#include <vector> struct Foo{std::vector<int> mem={1,2,3};// list-initialization of a non-static memberstd::vector<int> mem2;     Foo(): mem2{-1,-2,-3}{}// list-initialization of a member in constructor}; std::pair<std::string,std::string> f(std::pair<std::string,std::string> p){return{p.second, p.first};// list-initialization in return statement} int main(){int n0{};// value-initialization (to zero)int n1{1};// direct-list-initialization std::string s1{'a','b','c','d'};// initializer-list constructor callstd::string s2{s1,2,2};// regular constructor callstd::string s3{0x61,'a'};// initializer-list ctor is preferred to (int, char) int n2={1};// copy-list-initializationdouble d=double{1.2};// list-initialization of a prvalue, then copy-initauto s4=std::string{"HelloWorld"};// same as above, no temporary// created since C++17 std::map<int,std::string> m=// nested list-initialization{{1,"a"},{2,{'a','b','c'}},{3, s1}}; std::cout<< f({"hello","world"}).first// list-initialization in function call<<'\n'; constint(&ar)[2]={1,2};// binds an lvalue reference to a temporary arrayint&& r1={1};// binds an rvalue reference to a temporary int//  int& r2 = {2}; // error: cannot bind rvalue to a non-const lvalue ref //  int bad{1.0}; // error: narrowing conversionunsignedchar uc1{10};// okay//  unsigned char uc2{-1}; // error: narrowing conversion     Foo f; std::cout<< n0<<' '<< n1<<' '<< n2<<'\n'<< s1<<' '<< s2<<' '<< s3<<'\n';for(auto p: m)std::cout<< p.first<<' '<< p.second<<'\n';for(auto n: f.mem)std::cout<< n<<' ';for(auto n: f.mem2)std::cout<< n<<' ';std::cout<<'\n'; [](...){}(d, ar, r1, uc1);// has effect of [[maybe_unused]]}

      Output:

      world0 1 1abcd cd aa1 a2 abc3 abcd1 2 3 -1 -2 -3

      [edit]Defect reports

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

      DRApplied toBehavior as publishedCorrect behavior
      CWG 1288C++11list-initializing a reference with a brace-enclosed initializer list of a
      single initializer clause always bound the reference to a temporary
      bind to that initializer
      clause if valid
      CWG 1290C++11the lifetime of the backing array was not correctly specifiedspecified same as other
      temporary objects
      CWG 1324C++11initialization considered first for initialization from{}aggregate initialization
      considered first
      CWG 1418C++11the type of the backing array lackedconstconst added
      CWG 1467C++11same-type initialization of aggregates and character
      arrays was prohibited; initializer-list constructors had
      priority over copy constructors for single-clause lists
      same-type initialization
      allowed; single-clause
      lists initialize directly
      CWG 1494C++11when list-initializing a reference with an initializer clause of an
      incompatible type, it was unspecified whether the temporary
      created is direct-list-initialized or copy-list-initialized
      it depends on the
      kind of initialization
      for the reference
      CWG 2137C++11initializer-list constructors lost to copy
      constructors when list-initializingX from{X}
      non-aggregates consider
      initializer-lists first
      CWG 2252C++17enumerations could be list-initialized from non-scalar valuesprohibited
      CWG 2267C++11the resolution ofCWG issue 1494 made clear
      that temporaries could be direct-list-initialized
      they are copy-list-initialized
      when list-initializing references
      CWG 2374C++17direct-list-initialization of an enum allowed too many source typesrestricted
      CWG 2627C++11a narrow bit-field of a larger integer type can be promoted to
      a smaller integer type, but it was still a narrowing conversion
      it is not a
      narrowing conversion
      CWG 2713C++20references to aggregate classes could not
      be initialized by designated initializer lists
      allowed
      CWG 2830C++11list-initialization did not ignore the top-level cv-qualificationignores
      CWG 2864C++11floating-point conversions that overflow were not narrowingthey are narrowing
      P1957R2C++11conversion from a pointer/pointer-to-member
      tobool was not narrowing
      considered narrowing
      P2752R3C++11backing arrays with overlapping lifetime could not overlapthey may overlap

      [edit]See also

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

      [8]ページ先頭

      ©2009-2025 Movatter.jp