0

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 << " ";
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
JustForLong
  • 109
  • 8
  • "Addresses"? What exactly are you talking about? Where do "addresses" come into the picture and why are you mentioning them? – AnT stands with Russia Feb 27 '19 at 01:49
  • 2
    That `&` makes `arrEntry` a reference to an element in `arr`. What this really means to you is best looked up in your preferred C++ language reference or textbook. – user4581301 Feb 27 '19 at 01:50
  • How the range-based `for` works is an implementation detail you don't need to worry about, but if you're interested, here's a pretty good documentation page: https://en.cppreference.com/w/cpp/language/range-for Note: You need to have a pretty good handle on basic iterators to have a hope of understanding most of it. – user4581301 Feb 27 '19 at 01:52
  • Alright my confusion starts at the "&". If it wasn't there, the way the loop would work is arrEntry would be assigned to 1, and then 2, and then 3,... and it would print each out. – JustForLong Feb 27 '19 at 01:56
  • 2
    An example of where the `&` becomes useful: `for(int arrEntry : arr){ arrEntry++; }` would have no discernible after effects. `arrEntry` is just another local variable with a copy of a value in the array. A decent compiler would discard the loop as pointless. But with `for(int & arrEntry : arr){ arrEntry++; }` `arrEntry` IS an entry in the array and the `++` affects the value in the array. `for(const int &arrEntry : arr)` may have some performance advantages over `for(int arrEntry : arr)`, no copy is made, but a decent compiler would figure that out on its own and eliminate the copy anyway. – user4581301 Feb 27 '19 at 02:02
  • have you ran the code? Did you see with `&` is still prints `1 2 3 4 5`. So clearly no addresses come into play. – bolov Feb 27 '19 at 02:10

3 Answers3

4

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
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
alter_igel
  • 6,899
  • 3
  • 21
  • 40
  • Okay I'm starting to get this! – JustForLong Feb 27 '19 at 02:37
  • Note to those coming in from C# and similar languages: Reference type as used in this answer does not mean what you are used to. Make sure you understand the second half of the sentence before proceeding. – user4581301 Feb 27 '19 at 02:38
2

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 (e.g. calling a function that returns a std::vector<int> by value.

Cruz Jean
  • 2,761
  • 12
  • 16
1

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 << " ";
}
  • if `arrEntry` were a reference to `arr`, then its type would actually have to be `int(&)[5]`. You could reword your answer to be clearer about what `arrEntry` is – alter_igel Feb 27 '19 at 02:27
  • `arrEntry` is reference to `arr` entry not to entire `arr`. And result might be the same but some cases performance is better when used references. –  Feb 27 '19 at 02:33