er344tre
er344tre

Reputation: 105

Iterating through container - when to use reference and when not

In the code below, we don't dereference y (it is error in fact), but we do dereference z. Can someone explain why so?

 #include <iostream>  
 #include <vector>  


int main()   
{  
std::vector <int> x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 for( auto y : x ) 
     std::cout << y << " ";  

std::cout<<std::endl;

for(auto z = x.begin();z!=x.end();++z)
    std::cout<<*z<<" ";
}

Upvotes: 0

Views: 76

Answers (3)

wally
wally

Reputation: 11002

In the code below, we don't dereference y (it is error in fact), but we do dereference z. Can someone explain why so?

We don't because the compiler does.


The range based for loop: auto y : x also uses the begin and end functions, and it dereferences the iterators for you. It is equivalent to the following syntax:

auto && __range = range_expression;     // reference that we'll get to use
auto __begin = begin_expr;              // get iterator
auto __end = end_expr;
for(; __begin != __end; ++__begin) {
    range_declaration = *__begin;       // dereference iterator
    loop_statement
}

The iterators in turn perform the dereferencing by having overloaded the * operator to return a reference.


So in the question the second part actually does exactly what the range based for does for you 'behind the scenes'.

Upvotes: 1

JenyaKh
JenyaKh

Reputation: 2498

The second construct is an explicit way of loop iteration via iterators.

The first one is a syntactic sugar. You can read about it here: http://en.cppreference.com/w/cpp/language/range-for. It can be seen there that the construct is transformed into something like:

auto && __range = range_expression ; 
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) { 
    range_declaration = *__begin; 
    loop_statement 
} 

The key place for understanding is range_declaration = *__begin. Here range_declaration is y and it is assigned from real iterator.

Upvotes: 2

Tas
Tas

Reputation: 7111

Because you are using two different types. auto y : x is saying that y will be the actual element itself (1, 2 etc), whereas auto z = x.begin() is saying that z will be nn iterator, which you need to dereference to get the actual value.

You should simply prefer to use the first, because the code is shorter and more easily readable.

Upvotes: 1

Related Questions