Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why in this example there is "for(auto& x : v)" and not "for(auto x : &v)"?

I found this code in Bjarne Stroustrup's The C++ programming language (4. edition).

In this example, as far as my understanding goes, we increment x without copying the value of v into x. My question is, that why do we reference to x, and not to v?

I tried understanding the problem by breaking it down and writing it down onto a paper, that what would happen in the memory simplified, but I do not get it.

void increment()
{
   int v[]={0,1,2,3,4,5,6,7,8,9};

   for(auto& x : v)
      {
        ++x;
      }
}
like image 451
Balázs Börcsök Avatar asked Aug 08 '19 09:08

Balázs Börcsök


2 Answers

This is a good beginner question. Have a look at what cppreference has on range-based for loops. Because v is an array type, this above snippet expands to

{
    auto && __range = v;

    for (auto __begin = __range, __end = (__range + bound);
        __begin != __end; ++__begin)
    {
        auto& x = *__begin;
        ++x
    }
} 

where "bound is the number of elements in the array (if the array has unknown size or is of an incomplete type, the program is ill-formed)" [citation from the above link].

We can see, that the machinery behind such a range-based for loop makes sure that we act on an lvalue reference to v here: auto && __range = v uses type deduction with a forwarding reference, which does the right thing.

In short, with the auto& x part in the loop, you control what is being initialized when the iterators pointing into the range are dereferenced (*__begin). For example, with auto& x you get a reference to an element in the range (which you can change, affecting the range), with const auto& x, you get a const-qualified reference to an element in the range (which you can't mutate). You obtain copies of each element with auto x, and const-qualified copies of each element with const auto x, but the latter is hardly useful.

like image 114
lubgr Avatar answered Sep 25 '22 20:09

lubgr


Because the for loop is changing the array elements, so you want a reference to each element in order to increment them.

If you incorrectly had:

for(auto x : v)
{
    ++x;
}

nothing in v would change because x is a copy of the array elements.

Making it:

for(auto x : &v)
{
    ++x;
}

doesn't compile because &v is the address of the array (not the address of the first element in the array as v is) and is invalid in range expressions.

But using:

for(auto& x : v)
{
    ++x;
}

now makes x a reference to elements in v and can therefore change them.

like image 30
Paul Evans Avatar answered Sep 26 '22 20:09

Paul Evans