-1

`

vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
vector<int> res;
res.push_back(nums.front());
vector<int>::iterator it = nums.begin();
vector<int>::iterator it2 = res.begin();
++it;
cout << "it2 -> " << *it2 << endl;
cout << "it + it2 " << *it + *it2 << endl;

while(it != nums.end())
{
    res.push_back(*it + *it2);
    cout << "it : " << *it << endl;
    cout << "it2 : " << *it2 << endl;
    cout << "pushed " << (*it + *it2) << " ";
    it++;
    it2++;
}
    
it = nums.begin();
while(it != nums.end())
{
    cout << *it << " ";
    ++ it;
}
cout << endl;

it2 = res.begin();
while(it2 != res.end())
{
    cout << *it2 << " ";
    ++it2;
}
cout << endl;

` The output of the above is :

it2 -> 1
it + it2 3
it : 2
it2 : 17858448
pushed 17858450 it : 3
it2 : 17825984
pushed 17825987 1 2 3
1 3 17825987

I can't understand why the value of *it2 is normal outside the loop but inside it, it's showing the address.

I was trying to find the running sum of a 1d array using vectors. I learning iterators and hence am interested in understanding exactly why the above code is not working.

Anant
  • 3
  • 2
  • 2
    Don't modify the content of your vector while iterating over it, adding or deleting items will invalidate the iterator. And why use iterators at all? Have a look at [ranged for loops](https://en.cppreference.com/w/cpp/language/range-for). And do you know you can initialize a vector like this : `std::vector values{1,2,3,4,5,6};` ? – Pepijn Kramer Nov 20 '22 at 08:53
  • Why do you think those numbers are addresses? – molbdnilo Nov 20 '22 at 08:55
  • When you modify the size of a vector, you can no longer rely on iterators created previously being valid. `it2` is and iterator to `res` which gets modified in the loop and therefore dereferencing `it2` after the first `res.push_back(...);` is undefined behaviour. – fabian Nov 20 '22 at 08:59
  • See [Iterator invalidation rules for C++ containers](https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers) – Jason Nov 20 '22 at 09:21

1 Answers1

0

Those aren't addresses, they are garbage integers.

Your code is suffering from iterator invalidation. When you add an item to a vector you potentially invalidate any iterator that is pointing to it. This happens because adding an element to a vector may cause the vector to reallocate the memory it uses to hold it's elements. If this happens then you are left with an iterator that is no longer pointing at the correct memory, so you get garbage values.

The simple fix is to use integer offsets instead of iterators for this code

vector<int>::iterator it = nums.begin();
size_t off2 = 0;
++it;
cout << "res[off2]  -> " << res[off2] << endl;
cout << "it + res[off2]  " << *it + res[off2] << endl;

while(it != nums.end())
{
    res.push_back(*it + res[off2]);
    cout << "it : " << *it << endl;
    cout << "res[off2] : " << res[off2] << endl;
    cout << "pushed " << (*it + res[off2]) << " ";
    it++;
    off2++;
}

Although since you seem to be always using the last item from res an even simpler fix would be to use res.back(). Without the printing that gives

vector<int>::iterator it = nums.begin();
++it;
while(it != nums.end())
{
    res.push_back(*it + res.back());
    it++;
}

An earlier version of this post was incorrect, thanks to Pepijn for putting me straight.

john
  • 85,011
  • 4
  • 57
  • 81