Reputation: 1
Why do the following code snippets give different outputs? (see outputs below)
Snippet 1:
vector<int> v;
v.push_back(1);
v.push_back(2);
vector<int>::const_iterator iterv1=v.begin();
vector<int>::const_iterator iterv2=v.begin();
for(;iterv1!=v.end();++iterv1){
for(;iterv2!=v.end();++iterv2){
cout << "*iterv1 = " << *iterv1 << " *iterv2 = " << *iterv2 << endl;
}
}
Ouptut:
*iterv1 = 1 *iterv2 = 1
*iterv1 = 1 *iterv2 = 2
Code snippet 2:
vector<int> v;
v.push_back(1);
v.push_back(2);
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
cout << "v[i] = " << v[i] << " v[j] = " << v[j] << endl;
}
}
Output:
v[i] = 1 v[j] = 1
v[i] = 1 v[j] = 2
v[i] = 2 v[j] = 1
v[i] = 2 v[j] = 2
I would have expected the same (numerical output. Clearly there is something I am not understanding about iterators. Can someone help?
Upvotes: 0
Views: 286
Reputation: 45675
Well, you don't reset iterv2
to the beginning in the inner loop. You should place the initialization code where it belongs: in the for-initialization.
Either just move the assignment in the for-initialization:
vector<int>::const_iterator iterv1;
vector<int>::const_iterator iterv2;
for(iterv1=v.begin();iterv1!=v.end();++iterv1){
for(iterv2=v.begin();iterv2!=v.end();++iterv2){
cout << "*iterv1 = " << *iterv1 << " *iterv2 = " << *iterv2 << endl;
}
}
Or even put the variables inside of the loop if they aren't needed afterwards:
for(vector<int>::const_iterator iterv1=v.begin();iterv1!=v.end();++iterv1){
for(vector<int>::const_iterator iterv2=v.begin();iterv2!=v.end();++iterv2){
cout << "*iterv1 = " << *iterv1 << " *iterv2 = " << *iterv2 << endl;
}
}
By the way, if you use C++11, you can make use of the two following new language-features: The auto
keyword can be used to leave out the type specification (not to be confused with dynamic typing, as this still is static typing, meaning that the compiler figures out the type and compiles it the same way as you wrote the type explicitly):
for(auto iterv1=v.begin();iterv1!=v.end();++iterv1){
for(auto iterv2=v.begin();iterv2!=v.end();++iterv2){
cout << "*iterv1 = " << *iterv1 << " *iterv2 = " << *iterv2 << endl;
}
}
And the new syntax for range-based for-loop (similar to Java's) will make it a lot easier to both write and (far more important) to read:
for(auto iterv1 : v){
for(auto iterv2 : v){
cout << "*iterv1 = " << *iterv1 << " *iterv2 = " << *iterv2 << endl;
}
}
P.S. The same error would have happened if you moved the initializations outside of the loops in your index-based version:
// WRONG - SAME ERROR
int i = 0;
int j = 0;
for(;i<2;++i){
for(;j<2;++j){
cout << "v[i] = " << v[i] << " v[j] = " << v[j] << endl;
}
}
PP.S. Add spaces around operators to make your code slightly more readable. Most code style guidelines require that.
Upvotes: 3