LucioPhys
LucioPhys

Reputation: 161

c++: std::vector of std::vector inside a struct

I need to create a struct that sotres a std::vector<std::vector<int>> that will contain 4 vectors of ints. I tried the declaration I usually use for vector of vectors:

struct myStruct{
   std::vector<std::vector<int>> myVector(4);
};

but, when I compile, I get this error:

myProgram.cpp:79:52: error: expected identifier before numeric constant
     std::vector<std::vector<int>> myVector(4);
                                           ^
myProgram.cpp:79:52: error: expected ‘,’ or ‘...’ before numeric constant

I tried to declare the vector in the struct and then reserve 4 elements in the main(), in the following way:

struct myStruct{
   std::vector<std::vector<int>> myVector;
};

int main(){
   myStruct s;
   s.myVector.reserve(4);
   s.myVector[0].push_back(1);
   return 0;
}

In this way it compiles without errors, but I get a segmentation violation as soon as I try to push_back.

What is the proper way to do this task? And why can't I use the first declaration to specify the size of myVector? Thank you! :)

Upvotes: 3

Views: 2596

Answers (2)

aschepler
aschepler

Reputation: 72463

A default member initializer inside a class or struct must have an = token and/or {curly braces}.

std::vector<std::vector<int>> myVector{4};

[Note this would be trickier if the type were just std::vector<int>, since curly braces for a vector imply a sequence of elements. std::vector<int>{4} is a vector with size one whose one element is 4, not a vector of four zeroes. But here it's fine because {4} can't convert to std::initializer_list<std::vector<int>>, so that constructor overload isn't eligible, and the vector(size_type) constructor does win.]

The example program has undefined behavior because reserve does not change the size or create any elements. So s.myVector[0] is invalid since the vector is still empty. Remember, reserve is just a setup hint for the vector. Any valid program that uses reserve would still be valid if you removed all the reserve calls.

Using resize instead would do what you seem to mean: make the size of myVector equal to 4, by creating 4 empty element vectors. Then the push_back would add the number 1 to the first of those vectors, resulting in data {{1}, {}, {}, {}}.

int main(){
   myStruct s;
   s.myVector.resize(4);
   s.myVector[0].push_back(1);
   return 0;
}

Upvotes: 4

dj1986
dj1986

Reputation: 362

struct myStruct {
    std::vector<std::vector<int>> myVector{4};
};

int main() {
    myStruct s;
    s.myVector[0].push_back(1);
    s.myVector[0].push_back(2);
    s.myVector[0].push_back(3);
    s.myVector[0].push_back(4);

    s.myVector[1].push_back(11);
    s.myVector[1].push_back(21);
    s.myVector[1].push_back(31);
    s.myVector[1].push_back(41);

    cout << s.myVector[0][0] << " " << s.myVector[0][1] << " " << s.myVector[0][2] << " " << s.myVector[0][3] << " " << endl;
    cout << s.myVector[1][0] << " " << s.myVector[1][1] << " " << s.myVector[1][2] << " " << s.myVector[1][3] << " " << endl;

    return 0;
}

What is the proper way to do this task?

Hope this will answer your question.

Upvotes: 1

Related Questions