简体   繁体   中英

Range based for-loop with &

I haven't found a question that answers the part I'm confused on, and I apologize if someone did answer it.

I'm confused on whats going on in this for-loop, how is it looping through the addresses?

int arr[] = {1,2,3,4,5};
for(const int &arrEntry : arr){
     cout << arrEntry << " ";
}

Perhaps the placement of & is causing confusion. Remember that C++ doesn't care where you put spaces. Since this: for (const int &arrEntry : arr) is a declaration of a new variable arrEntry for use inside the loop, the use of & on the left-hand side of its name means we are defining an object that has a reference type, specifically arrEntry is a reference to a const int . This means that within the loop, arrEntry is not a copy of the data you're looping over, only a reference to it. The const means that you can't change its value.

If this were not a declaration, and if arrEntry were defined previously, then the expression &arrEntry would indeed be taking the address of arrEntry . Within the body of the loop, arrEntry is already defined, and so you can take its address with &arrEntry

int arr[] = {1,2,3,4,5};
for(const int &arrEntry : arr){
     cout << arrEntry << " "; // prints a const int
     cout << &arrEntry << " "; // prints a pointer to a const int
}

The range-based for loop in C++ is actually just syntactic sugar that is equivalent to the following (provided by cppreference :

for (range_declaration : range_expression) loop_statement;

// is equivalent to:

{
    auto && __range = range_expression ;
    for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {

        range_declaration = *__begin;
        loop_statement

    }
}

In the above code block, begin_expr and end_expr are equivalent to std::begin(__range) and std::end(__range) respectively.

So in the case of using const int &arrEntry , arrEntry is actually declared inside the "real" (normal) for loop and thus in each iteration it refers to a different object in the range, as if by using the raw iterators directly.

Note that this would not be possible if arrEntry was declared outside the normal for loop, as references cannot be repointed to refer to a different object.

Another important (side) fact to consider is that range_expression is kept alive for the entire duration of the loop, which means you can use a prvalue there (eg calling a function that returns a std::vector<int> by value.

In your code, the &arrEntry is a reference to arr. This is implicit in the Ranged based For-Loop.

for(const int &arrEntry : arr){
     cout << arrEntry << " ";
}

You could do it without the reference, the result is the same. But notice the value of arr is copied to arrEntry.

for(const int arrEntry : arr){
     cout << arrEntry << " ";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM