Search code examples
c++vectorinitializer-list

Why are the values of vector<int> inside initializer_list changing after calling the constructor?


I'm new to C++ and trying to setup a matrix class. The matrix is created from an initializer_list containing vector<int> entries as the rows of the matrix. One of the methods of this class should be get_row(size_t rownumber). When I call the implemented method from the constructor, it returns the correct result. But when calling the same method from main(), the first two elements of each row contain some huge numbers that shouldn't be in there.

I assume the problem is somehow related to pointers. Though, I can't really find where the elements of the matrix could be overwritten between the call inside the constructor and the call inside main. When I went into debug mode in Eclipse the pointers seemed to point to the expected addresses ...

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

template<typename T> class myMatrix {
    private:
        initializer_list<vector<int>>::iterator it;
        initializer_list<vector<int>> matrix;
    public:
        myMatrix(initializer_list<T> values) {
        matrix = values;

        vector<int> chosen_row = get_row(1);
        cout << "Called from constructor: ";
        for (unsigned i = 0; i != chosen_row.size(); i++) {
            cout << chosen_row.at(i) << " ";
        }
        }
    vector<int> get_row(size_t x) {
        it = matrix.begin() + x - 1;
        return (*it);
        }
};

int main(int argc, char *argv[]) {
    myMatrix<vector<int>> test{{3, 4, 5, 2}, {7, 2, 3, 4}};
    vector<int> chosen_row = test.get_row(1);
    cout << endl << "Called from main: ";
    for (unsigned i = 0; i != chosen_row.size(); i++) {
        cout << chosen_row.at(i)<< " " ;
    }
    return 0;
}

The Output is the following:

Called from constructor: 3 4 5 2 
Called from main: 187072144 22084 5 2

Can someone please tell me, where the error happens? Thank you very much!


Solution

  • initializer_list is a lightweight view over a const array that doesn't own (or extend the lifetime of) any of its elements.

    When you write {{3, 4, 5, 2}, {7, 2, 3, 4}}, you're creating a temporary array of vectors on the stack - the initializer_list is basically a pointer+length view into it. After your matrix has been constructed, that array is destroyed.

    Use a container such as vector instead of initializer_list inside your matrix implementation to solve the issue. E.g.

    private:
        vector<vector<int>>::iterator it;
        vector<vector<int>> matrix;