简体   繁体   中英

What is the difference between iterator and &iterator?

    vector<int> A = {1, 2, 3};
    
    //case 1
    for(auto it : A){
        it = 0;
    }
    
    print(A) //OUTPUT -> 1, 2, 3
    
    //case 2
    for(auto &it : A){
        it = 0;
    }
    
    print(A) //OUTPUT -> 0, 0, 0

How are 'it' and '&it' different? How exactly are iterator and &iterator working?

Case 1

The auto keyword(without the use of & ) infers a non-reference type. This means in your case 1, auto infers it to be of type int . This is a non-reference type, meaning that the values from the std::vector will get copied into the loop variable it , which in turn means that any changes made to it will not be reflected in the std::vector itself.

Case 2

In case 2, however, due to the use of & in auto , the loop variable it is of type int& which is a reference type and any change you make on it will be reflected on the original vector.

When using & for the type in a foreach loop, the loop will go over references to the items in the vector.

I might be more readable if you write the seconds loop as:

    for(auto& it : A){
        it = 0;
    }
    

And then it means that the element of type auto will be a reference to the element in A .

When not using & , each element is copied in each iteration, so when you assign to it, it has no effect on the original vector.

When you use auto in C++11 and later, the compiler has to deduce the type.
According to the documentation :

type is deduced using the rules for template argument deduction .

This means that qualifiers like const and volatile , as well as being a pointer or a refernce, are not a part of the deduced type. In other words the deduced type will be the basic type of the expression assigned to the auto variable, without const , volatile or pointer/reference indirection.

Example: If you have a function like:

A & GetA() { ... }

You can use it in several ways. In all of them auto will be deduced as A , but the type of a will be different:

auto a = GetA();         // The type of `a` will be `A`, and a copy will be made.
auto & a = GetA();       // The type of `a` will be `A&`. No copy will be made.
auto const & a = GetA(); // The type of `a` will be `A const&`. No copy will be made and the compiler will verify you do not modify the referenced object.
// etc.

Aplying this principle to your case:

  1. for(auto it : A) :
    auto will be deduced as int and this will be the type of it . Therefore a copy will be made of the elements in A and placed into it . No modification of the element copy will affect the original vector.
  2. for(auto & it : A) :
    auto will still be deduced as int , but it will be of type int& . Therefore no copy will be made, rather we'll get a reference to the vector element. This is why the code was able to modify the vector.

On a side note: using a range based loop (like you do), means that the variable of the loop will be assigned to the actual elements (or their refernce of course) in the collection. This is actually not an iterator, so using it as a variable name is misleadsing. Better to use eg a in your case.

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