Vectors of vectors of objects

Hey guys, so I need some help with manipulating a set of containers. I created a vector that contained vectors of objects:

std::vector< std::vector<Terrain> > mapArray(num1, std::vector<Terrain>(num2));

where num1 and num2 are arbitrary numbers. and Terrain is the class of objects I'm trying to store.

I want to be able to use push_back on both the main vector and the vectors within the mapArray vector but I'm unsure of how to target the inner vectors with push_back. Can anyone help me with this?

I don't really have any formal training with containers and I've been trying to teach myself about them, so if this looks dumb, I won't be surprised, and I'll expect someone to tell me.

Alternatively, if anyone has a better idea of how to dynamically store a 2D array of objects, I'd be happy to consider that as well. Vectors just seemed to be the best choice.
1
2
mapArray.push_back(tvec); // assume tvec is of type vector<Terrain>
mapArray[0].push_back(ter); // assume ter is of type Terrain 

You can treat mapArray as an array of vector<Terrain>s to access each vector in it.
Am I correct in assuming that I need to initialize each object before pushing it back?

Edit:

I'm tying to initialize the number I need with a for loop like so:

1
2
3
4
5
6
7
8
for(int i = 0; i < num; i++)
{
        tvec = new std::vector<Terrain>;
        mapArray.push_back(*tvec);

	terrain = new Terrain();
	mapArray[i].push_back(*terrain);
}


having declared tvec and terrain earlier as:

1
2
Terrain *terrain; 
std::vector<Terrain> *tvec;


Is this appropriate, or am I doing something wrong? It wouldn't allow me to pass arguments into push_back without passing them as a pointer which I don't entirely understand.
Last edited on
No, you're wrong. Basically, if you have a new in your code in 95% of all cases you're doing something wrong.

1
2
3
4
5
6
std::vector< std::vector<Terrain> > mapArray;
for(int i=0; i<num; ++i) {
    std::vector<Terrain> tvec;
    tvec.push_back(Terrain());
    mapArray.push_back(tvec); 
}


With a compiler (and standard library) that supports C++11, you could do this a bit nicer:

1
2
3
4
std::vector< std::vector<Terrain>> mapArray;
for(int i=0; i<num; ++i) {
   mapArray.emplace_back(1,Terrain{});
}



Of course if that's all you're gonna do, you could just leave your constructor at that:

std::vector< std::vector<Terrain> > mapArray(num1, std::vector<Terrain>(num2));

This will initialize mapArray to contain num1 vectors each of which contains num2 Terrains (which are all copy constructed from Terrain()).
Last edited on
And if I'm reading this correctly, then that will give me a number num tvec vectors each containing a single Terrain object? So if I wanted to create lets say 8 tvec vectors with 8 Terrain objects then I would need to do something along these lines...?:

1
2
3
4
5
6
7
8
9
10
11
12
std::vector< std::vector<Terrain> > mapArray(num1, std::vector<Terrain>(num2));

int num = 8;

for(int i=0; i<num; ++i) {
    std::vector<Terrain> tvec;

    for(int j = 0; j < num; ++j)
        tvec.push_back(Terrain());

    mapArray.push_back(tvec); 
}


No. If you wanted 8 vectors each containing 8 terrain objects you'd do this:

std::vector< std::vector<Terrain> > mapArray(8, std::vector<Terrain>(8));

That is assuming Terrain is both default and copy-constructible.


If you know the size of these things at compile time (that is, they neither need to grow or shrink at runtime and you don't need some in-program option for setting those), you should probably use std::array (or std::tr1::array if you use some older library/compiler):

std::array<std::array<Terrain, 8>, 8> mapArray;
Last edited on
Let me rephrase my question:

If I wanted to push multiple objects onto one of the inner vectors I would use a loop that looked like this:

1
2
3
4
for(int i = 0; i < num; ++i)
{
    mapArray[0].push_back(Terrain());
}


and so assuming that I need to add three new vectors with num objects in them at the same time, I could use the loop I mentioned in my last post to accomplish that, right?

I realize that I can initialize an 8x8 at the beginning, but I'm curious about dynamically allocating multiple at the same time.
Yeah, in that case you're correct. You could just try it instead of asking though (saves you a lot of time in the long run, trust me. You can still ask if you can't get it to work).
Ok thanks. Yeah, I was going to if you hadn't responded. I can't test where I'm at right now, so I figured I'd have time to get a response. Anyway, thanks again! Great help from both of you!
If you have web access, you can always use
http://ideone.com/

or http://liveworkspace.org/ (seems a lot better to me, the c++ compiler at ideone is pretty old).
@hanst99 They (ideone) updated the compiler to gcc-4.7.2
Topic archived. No new replies allowed.