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?
CodePudding user response:
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.
CodePudding user response:
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.
CodePudding user response:
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.
Simply put, 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:
for(auto it : A)
:
auto
will be deduced asint
and this will be the type ofit
. Therefore a copy will be made of the elements inA
and placed intoit
. No modification of the element copy will affect the original vector.for(auto & it : A)
:
auto
will still be deduced asint
, butit
will be of typeint&
. 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 e.g. a
in your case.