1

I'm trying to cloning the vector itself, for example if the vector is [2,3] it will become [2,3,2,3].

This is my program:

#include <iostream>
#include <vector>
using namespace std;

int main() 
{
    vector<int> a;
    
    a.push_back(2);
    a.push_back(3);
    
    for(int i: a)
    {
        a.push_back(i);
    }
        
    for(int i: a)
        cout << i << " ";
        
    return 0;
}

So I'm just pushing the elements to the vector itself but the output is [2,3,2,0]. I don't understand why.

Help me with this problem.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • 2
    You can't add or remove items of a vector while iterating over it the way you are. – drescherjm Jul 26 '22 at 17:13
  • If you modify the number of elements in the list, iterators may get invalidated. Your code results in UB for this reason... – fabian Jul 26 '22 at 17:14
  • Related: [https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers](https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers) – drescherjm Jul 26 '22 at 17:14
  • 1
    Does this answer your question? [Iterator invalidation rules for C++ containers](https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers) – drescherjm Jul 26 '22 at 17:15
  • When does it stop? You add the previous 2 elements to the vector, but now it is 4, so you add the 4 elements to the end, etc. – Thomas Matthews Jul 26 '22 at 19:56

3 Answers3

4

Range-for is syntactic sugar for an iterator-based for-loop, and std::vector::push_back() can invalidate iterators like the ones being used internally by the range-for:

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

You can use std::copy() after a resize():

vector<int> a;
a.push_back(2);
a.push_back(3);

auto size = a.size();
a.resize(size * 2);
std::copy(a.begin(), a.begin() + size, a.begin() + size);
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • @UselessKid: Hmm, looking at the `insert()` docs what I have is still [UB](https://en.wikipedia.org/wiki/Undefined_behavior). Back to the drawing-board :( – genpfault Jul 26 '22 at 17:41
  • @genpfault, why does it cause UB, it works fine for me. –  Jul 26 '22 at 17:55
  • @UselessKid: See the note for form (4) on [the `insert()` page](https://en.cppreference.com/w/cpp/container/vector/insert): "The behavior is undefined if `first` and `last` are iterators into `*this.`" – genpfault Jul 26 '22 at 17:58
4

Do not use range base iterators while changing the container you are iterating. In this case, just store the size of the vector before inserting and then use a regular index based loop.

int sz = a.size();

for(int i =0 ; i < sz ; ++i)
{
   a.push_back(a[i]);
}
0

You are iterating over the vector which is being changed at the same time.

//This is problematic
for(int i: a)
{
  a.push_back(i);
}

You can instead do it this way:

#include <iostream>
#include <vector>
using namespace std;

int main() 
{
    vector<int> a;
    
    a.push_back(2);
    a.push_back(3);
    
    vector<int> b = a; //Store contents in another vector
    
    for(int i: b)
    {
        a.push_back(i);
    }
        
    for(int i: a)
        cout << i << " ";
        
    return 0;
}