Reputation: 55
So, what is the difference between these two statement:
for(auto i : VectorName){}
for(auto i = VectorName.begin(); i != VectorName.end(); i++){}
For example, I have this program:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<char> vec = {'H','e','l','l','o','W','o','r','l','d','!'};
for(auto i = vec.begin(); i != vec.end(); i++) // This loop has error
{
cout << i << endl;
}
for(auto k : vec) //This loop has no problem
{
cout << k << endl;
}
return 0;
}
I am confused because in this example in this Microsoft docs:
// cl /EHsc /nologo /W4
#include <deque>
using namespace std;
int main()
{
deque<double> dqDoubleData(10, 0.1);
for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
{ /* ... */ }
// prefer range-for loops with the following information in mind
// (this applies to any range-for with auto, not just deque)
for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
{ /* ... */ }
for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
{ /* ... */ }
for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
{ /* ... */ }
}
They noted that the range for statement is not better than the regular one.
Upvotes: 1
Views: 347
Reputation: 10998
So, what is the difference between these two statement:
for(auto i : VectorName){} for(auto i = VectorName.begin(); i != VectorName.end(); i++){}
The first one will iterate through every item in the collection; i
is a copy of the item.
The second one gives you more control over the range; i
is an iterator, dereference to access item.
Upvotes: 0
Reputation: 801
The difference in your case is, that the first version with iterators, well, uses iterators (that's why cout << i << endl;
is not working), and the second version (the range-based for loop) gives you either a copy, a reference, or const reference.
for(auto i = vec.begin(); i != vec.end(); i++)
{
cout << i << endl; // should be *i
}
uses iterators (vec.begin()
gives you an iterator to the first element).
for(auto i : vec)
{
cout << i << endl;
}
uses copies of elements in your vector.
for(auto& i : vec)
{
cout << i << endl;
}
uses references to your vector elements.
Upvotes: 3
Reputation: 5493
Regular for loop uses an explicit loop variable, in your examples an iterator i
or iter
(many times it is just an integer). To access elements in a vector for example, you need to use the loop variable to extract the elements from the vector.
Range-based for loops automatically gives you the elements inside the container you loop over, so there is no need to extract the elements inside the loop, you can immediately use k
/elem
.
About the comment you mention: that specific range-based style with no references is usually bad for performance (if the copy is unnecessary).
Upvotes: 0
Reputation: 217135
In
for (auto i = vec.begin(); i != vec.end(); i++)
{
//cout << i << endl; // should be cout << *i << endl;
auto& k = *i;
cout << k << endl;
}
i
is an iterator, you have to deference it to retrieve the value to be nearly equivalent to second snippet.
Upvotes: 0