Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Range-basedfor loop(since C++11)

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      for
      range-for(C++11)
      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
       
       

      Executes afor loop over a range.

      Used as a more readable equivalent to the traditionalfor loop operating over a range of values, such as all elements in a container.

      Contents

      [edit]Syntax

      attr (optional)for (init-statement (optional)item-declaration:range-initializer)statement
      attr - any number ofattributes
      init-statement -(since C++20) one of
      (since C++23)

      Note that anyinit-statement must end with a semicolon. This is why it is often described informally as an expression or a declaration followed by a semicolon.

      item-declaration - a declaration for each range item
      range-initializer - anexpression orbrace-enclosed initializer list
      statement - anystatement (typically a compound statement)

      [edit]Explanation

      The above syntax produces code equivalent to the following except for the lifetime expansion of temporaries ofrange-initializer (seebelow)(since C++23) (the variables and expressions wrapped in/* */ are for exposition only):

      {

      auto&&/* range */=range-initializer ;
      for (auto/* begin */=/* begin-expr */,/* end */=/* end-expr */;
      /* begin */!=/* end */; ++/* begin */)
      {
      item-declaration= */* begin */;
      statement
      }

      }

      (until C++17)

      {

      auto&&/* range */=range-initializer ;
      auto/* begin */=/* begin-expr */;
      auto/* end */=/* end-expr */;
      for ( ;/* begin */!=/* end */; ++/* begin */)
      {
      item-declaration= */* begin */;
      statement
      }

      }

      (since C++17)
      (until C++20)

      {

      init-statement
      auto&&/* range */=range-initializer ;
      auto/* begin */=/* begin-expr */;
      auto/* end */=/* end-expr */;
      for ( ;/* begin */!=/* end */; ++/* begin */)
      {
      item-declaration= */* begin */;
      statement
      }

      }

      (since C++20)

      range-initializer is evaluated to initialize the sequence or range to iterate. Each element of the sequence, in turn, is dereferenced and is used to initialize the variable with the type and name given initem-declaration.

      item-declaration can be one of the following:

      Exposition-only expressions/* begin-expr */ and/* end-expr */ are defined as follows:

      • If the type of/* range */ is a reference to an array typeR:
      • IfR is of boundN,/* begin-expr */ is/* range */ and/* end-expr */ is/* range */+ N.
      • IfR is an array of unknown bound or an array of incomplete type, the program is ill-formed.
      • If the type of/* range */ is a reference to a class typeC, and searches in the scope ofC for the names “begin” and “end” each find at least one declaration, then/* begin-expr */ is/* range */.begin() and/* end-expr */ is/* range */.end().
      • Otherwise,/* begin-expr */ isbegin(/* range */) and/* end-expr */ isend(/* range */), where “begin” and “end” are found viaargument-dependent lookup (non-ADL lookup is not performed).

      If the loop needs to be terminated withinstatement, abreak statement can be used as terminating statement.

      If the current iteration needs to be terminated withinstatement, acontinue statement can be used as shortcut.

      If a name introduced ininit-statement is redeclared in the outermost block ofstatement, the program is ill-formed:

      for(int i:{1,2,3})int i=1;// error: redeclaration

      [edit]Temporary range initializer

      Ifrange-initializer returns a temporary, its lifetime is extended until the end of the loop, as indicated by binding to the forwarding reference/* range */.

      Lifetimes of all temporaries withinrange-initializer are not extended unless they would otherwise be destroyed at the end ofrange-initializer(since C++23).

      // if foo() returns by valuefor(auto& x: foo().items()){/* ... */}// until C++23 undefined behavior

      This problem may be worked around usinginit-statement:

      for(T thing= foo();auto& x: thing.items()){/* ... */}// OK
      (since C++20)


      Note that even in C++23 non-reference parameters of intermediate function calls do not get a lifetime extension (because in some ABIs they are destroyed in the callee, not in the caller), but that is only a problem for functions that are buggy anyway:

      using T=std::list<int>;const T& f1(const T& t){return t;}const T& f2(T t){return t;}// always returns a dangling referenceT g(); void foo(){for(auto e: f1(g())){}// OK: lifetime of return value of g() extendedfor(auto e: f2(g())){}// UB: lifetime of f2's value parameter ends early}
      (since C++23)

      [edit]Notes

      If therange-initializer is abraced-enclosed initializer list,/* range */ is deduced to be a reference to astd::initializer_list.

      It is safe, and in fact, preferable in generic code, to use deduction to forwarding reference,for(auto&& var: sequence).

      The member interpretation is used if the range type has a member named “begin” and a member named “end”. This is done regardless of whether the member is a type, data member, function, or enumerator, and regardless of its accessibility. Thus a class likeclass meow{enum{ begin=1, end=2};/* rest of class */}; cannot be used with the range-basedfor loop even if the namespace-scope “begin”/“end” functions are present.

      While the variable declared in theitem-declaration is usually used in thestatement, doing so is not required.

      As of C++17, the types of the/* begin-expr */ and the/* end-expr */ do not have to be the same, and in fact the type of the/* end-expr */ does not have to be an iterator: it just needs to be able to be compared for inequality with one. This makes it possible to delimit a range by a predicate (e.g. "the iterator points at a null character").

      (since C++17)

      When used with a (non-const) object that has copy-on-write semantics, the range-basedfor loop may trigger a deep copy by (implicitly) calling the non-constbegin() member function.

      If that is undesirable (for instance because the loop is not actually modifying the object), it can be avoided by usingstd::as_const:

      struct cow_string{/* ... */};// a copy-on-write stringcow_string str=/* ... */; // for (auto x : str) { /* ... */ } // may cause deep copy for(auto x:std::as_const(str)){/* ... */}
      (since C++17)
      Feature-test macroValueStdFeature
      __cpp_range_based_for200907L(C++11)Range-basedfor loop
      201603L(C++17)Range-basedfor loop withdifferentbegin/end types
      202211L(C++23)Lifetime extension for all temporary objects inrange-initializer

      [edit]Keywords

      for

      [edit]Example

      Run this code
      #include <iostream>#include <vector> int main(){std::vector<int> v={0,1,2,3,4,5}; for(constint& i: v)// access by const referencestd::cout<< i<<' ';std::cout<<'\n'; for(auto i: v)// access by value, the type of i is intstd::cout<< i<<' ';std::cout<<'\n'; for(auto&& i: v)// access by forwarding reference, the type of i is int&std::cout<< i<<' ';std::cout<<'\n'; constauto& cv= v; for(auto&& i: cv)// access by f-d reference, the type of i is const int&std::cout<< i<<' ';std::cout<<'\n'; for(int n:{0,1,2,3,4,5})// the initializer may be a// braced-enclosed initializer liststd::cout<< n<<' ';std::cout<<'\n'; int a[]={0,1,2,3,4,5};for(int n: a)// the initializer may be an arraystd::cout<< n<<' ';std::cout<<'\n'; for([[maybe_unused]]int n: a)std::cout<<1<<' ';// the loop variable need not be usedstd::cout<<'\n'; for(auto n= v.size();auto i: v)// the init-statement (C++20)std::cout<<--n+ i<<' ';std::cout<<'\n'; for(typedef decltype(v)::value_type elem_t; elem_t i: v)// typedef declaration as init-statement (C++20)std::cout<< i<<' ';std::cout<<'\n'; for(using elem_t= decltype(v)::value_type; elem_t i: v)// alias declaration as init-statement (C++23)std::cout<< i<<' ';std::cout<<'\n';}

      Output:

      0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 1 1 1 1 1 1 5 5 5 5 5 5 0 1 2 3 4 5 0 1 2 3 4 5

      [edit]Defect reports

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

      DRApplied toBehavior as publishedCorrect behavior
      CWG 1442C++11it was unspecified whether the lookup of non-member
      begin” and “end” includes usual unqualified lookup
      no usual unqualified lookup
      CWG 2220C++11the names introduced ininit-statement could be redeclaredthe program is ill-formed in this case
      CWG 2825C++11ifrange-initializer is a brace-enclosed initializer list,
      the non-member “begin” and “end” will be looked up
      will lookup member “begin
      and “end” in this case
      P0962R1C++11member interpretation was used if either
      member “begin” and “end” is present
      only used if both are present

      [edit]See also

      applies a unaryfunction object to elements from arange
      (function template)[edit]
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/range-for&oldid=172520"

      [8]ページ先頭

      ©2009-2025 Movatter.jp