iamseiko iamseiko - 3 months ago 24
C++ Question

Order of inserting elements into a 2D Vector in c++

I was practicing with C++ vectors, and found a problem when I was inserting elements into a 2D vector. In the following example:

#include <iostream>
#include <vector>

void fillVector(std::vector<std::vector<int> > &vec) {
std::vector<int> list1;
vec.push_back(list1);
list1.push_back(1);
list1.push_back(2);

std::vector<int> list2;
list2.push_back(3);
list2.push_back(4);
vec.push_back(list2);

return;
}

int main() {
std::vector<std::vector<int> > vect;
fillVector(vect);

std::cout << "vect size: " << vect.size() << std::endl;

for(int i = 0; i < vect.size(); i++) {
std::cout << "vect in size: " << vect.at(i).size() << std::endl;
}
}


the size of the first inner-list is 0, and the size of the second inner-list is 2. The only difference between
list1
and
list2
is that
list1
is first inserted into the
vec
2D vector, before elements are inserted into it, while elements are first inserted into
list2
, before it is itself inserted into the 2D vector. After returning from the function, the elements inserted into
list1
are not printed, and its size remains the same.

I also attempted the first method with pointers instead,

std::vector<int> *list3 = new std::vector<int>();
vec.push_back(*list3);
list3->push_back(5);
list3->push_back(6);


However, the size of list3 when read from the calling function is still 0.
I don't understand the difference between the two approaches. Why does the list have to appended after it's elements are inserted?

Answer

vector.push_back(var) makes a copy of var and inserts it into the vector. If you use push_back() on an empty list, it copies the empty list into the vector. Changing values in the list after this does not affect the copy that was inserted into the vector. This is because you are passing an actual object to push_back(), not a pointer to an object.

In the third example, you take a step in the right direction, but you de-reference the list before you pass it in, so push_back() makes a copy of what is at that address.

A simple solution to the problem is to always set your values before you insert the list into the vector.

If you wish to be able to change the values after the list is inserted, use vect.at(i).push_back(val) to add a value to the list at i. You could also make the vector contain pointers to other vectors, rather than the vectors themselves:

void fillVector(std::vector<std::vector<int> *> &vec) {
    std::vector<int> *list1 = new std::vector<int>(); //Remember to allocate memory since we're using pointers now
    list1->push_back(1);
    list1->push_back(2); 
    vec.push_back(list1); // Copy the pointer that is list1 into vec

    std::vector<int> *list2 = new std::vector<int>();
    vec.push_back(list2); // Copy the pointer that is list2 into vec
    list2->push_back(3);
    list2->push_back(4);
    return;
}

int main() {
    std::vector<std::vector<int> *> vect; // Vector of pointers to vectors
    fillVector(vect);

    std::cout << "vect size: " << vect.size() << std::endl;

    for(int i = 0; i < vect.size(); i++) {
        std::cout << "vect in size: " << vect.at(i)->size() << std::endl;
    }
}
std::vector<std::vector<int> *> vec = new; // Vector of pointers
Comments