In the below example, i
has function scope. But it seems that I cannot use i
in the second for loop. Why does for (i : v1)
not work, but for (int i : v1)
works?
#include<iostream> #include<string> #include<vector> int main() { std::vector<int> v1; int i; while(std::cin>>i) { v1.push_back(i); } for(i : v1) //for (int i:v1) works std::cout<<i<<"\t"; cout<<std::endl; return 0; }
Often the variable that controls a for loop is needed only for the purposes of the loop and is not used elsewhere. When this is the case, it is possible to declare the variable inside the initialization portion of the for.
Declaring Loop Control Variables Inside the for Loop, When you declare a variable inside a for loop, there is one important point to remember: the scope of that variable ends when the for statement does. (That is, the scope of the variable is limited to the for loop.)
Range-based for loop in C++ Range-based for loop in C++ is added since C++ 11. It executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.
Example 1: Ranged for Loop Using Array Note: The ranged for loop automatically iterates the array from its beginning to its end. We do not need to specify the number of iterations in the loop.
It's a syntactical issue that a range-based for
loop requires a declaration of a named variable, i.e. it requires a type specifier (cf, for example, cppreference.com):
for ( range_declaration : range_expression ) loop_statement
range_declaration - a declaration of a named variable, whose type is the type of the element of the sequence represented by range_expression, or a reference to that type. Often uses the auto specifier for automatic type deduction
Actually I don't know why your question got downvoted; I find your assumption quite OK; just the C++ syntax has decided to define it in another way.
The range-based for
is specifically intended to replace loops akin to the following (this is a somewhat simplistic case; range-based for
, especially the C++17 version, is more general than the example):
for (auto it = range.begin(), end = range.end(); it != end; ++it) { use(*it); }
In the majority of cases won't use the values at the different locations but will rather use the element at the location itself:
As a result the designers of range-based for
decided that references absolutely have to be supported. At the same time, it was intended to use a reasonably simplistic rewrite-rule for a range-based for
. The rule which is codified in the standard is this:
for (<range-decl>: <range>) { <body> }
is equivalent to
{ auto&& range = <range>; // keep the range alive! auto it = begin(range); // actually, reality is bit more complicated auto end = end(range); // actually, reality is a bit more complicated for (; it != end; ++it) { <range-decl> = *it; // this is the rewrite causing your issue <body> } }
In particular, the implication is that <range-decl>
is a declaration rather than just naming a variable. The reason for this requirement is that typically the entity used in front of the :
is a reference. However, references cannot be rebound. However, in each iteration of a loop a new reference can be used.
In principle the rewrite rule could work with using assignments if the <range-decl>
isn’t a declaration but rather an lvalue. That would yield its own share of odd behaviors:
for (T const& x: range)
and T const& x = 0; for (x: range)
: the former works while the latter is an error.T& x = get_reference(); for (x: range) {...}
) the loop would automatically assign all the values in a range to an object located somewhere. Normally the objects are either located on the stack or in the source range (when the variable is declared as a reference).It was consider more reasonable to only allow initialisations than supporting initialisation or assignments depending on how the variable is declared. Looking at the revision history of the proposals (N2930 and predecessors) doesn’t yield a discussion but I vaguely recall that ths point was discussed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With