Initialize vector of vectors after declaration.

Started by
17 comments, last by Servant of the Lord 9 years, 1 month ago

Hi again.

As i wrote earlier, i need to create a victor of fixed size vectors. As an example i used the following:

int array[N][100];

where N is given in execution.

Right now i use the following:

std::vector<std::vector<int> > myArray;

after getting N:

myArray.reserve(N);

The i have to go for each element to reserve the fixed size memory:

for( each element in myArray)

myArray.reserve(100);

Is there any better way to do this? I have about 10 different arrays so it's getting quite complex.

Advertisement

Don't know if this is the most efficient approach, but:


std::vector< std::vector<int> > myArray;
std::vector<int> initVal;
// you can initialize all the elements to 0 or other default value - maybe an invalid value such as -1 if only positive integers are expected.
initVal.resize(100, -1);
// don't know if the standard guarantees it, but testing on my machine indicates that the following will initialize all elements of initVal to 0
initVal.resize(100);
myArray.resize( N, initVal ); // initialize N elements by copying initVal


EDIT: Note: your approach will result in error, as reserve does not initialize the elements. It merely tells myArray that memory should be reserved (not filled). After myArray.reserve(N), the size of myArray = 0. Up to N elements can be added to myArray without further memory reallocation, but elements have to be added for the size to change.

I.e.,

myArray[0].reserve(100); // attempts to access element 0 which does not exist --> subscript out of range.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

If it really is fixed you can save yourselves some indirection by doing the array offset yourself rather than as a collection of collections.

For N and M dimensions, allocate N*M integers, then access elements with x*M+y.

If you have boost's libraries installed (which is a frequent recommendation) you can use Boost::MultiArray as a prebuilt class to handle multidimensional arrays if you prefer that style of data access.

As frob mentioned, and as I mentioned in your previous thread, it's really better to recognize the truth that your "2D" array is actually just 1D memory and, embracing that, use a 1D array and just index into it as if it were 2D.

.


std::vector<int> myVector(WIDTH * HEIGHT);

myVector[(y * WIDTH) + x] = 357;

.

This "std::vector<std::vector<int>>" isn't really 2D array anyway. It's an array of arrays, which means each row could accidentally be different sizes.

I'm sorry, but is really not an option in my case. It makes code quite unreadable. Not because of the simple aritmetic operation. It is because y use complex calculation to get an index. So adding a multiplication, an addition and 2 pair of parenthesis makes it even uglier. The point of this was to make code easier to read and mantain, but i think i'll stick with loop initialization.

Don't know if this is the most efficient approach, but:


std::vector< std::vector<int> > myArray;
std::vector<int> initVal;
// you can initialize all the elements to 0 or other default value - maybe an invalid value such as -1 if only positive integers are expected.
initVal.resize(100, -1);
// don't know if the standard guarantees it, but testing on my machine indicates that the following will initialize all elements of initVal to 0
initVal.resize(100);
myArray.resize( N, initVal ); // initialize N elements by copying initVal

EDIT: Note: your approach will result in error, as reserve does not initialize the elements. It merely tells myArray that memory should be reserved (not filled). After myArray.reserve(N), the size of myArray = 0. Up to N elements can be added to myArray without further memory reallocation, but elements have to be added for the size to change.

I.e.,

myArray[0].reserve(100); // attempts to access element 0 which does not exist --> subscript out of range.

This seems to be a good idea, i'll give it a try. Thanks

I'm sorry, but is really not an option in my case. It makes code quite unreadable. Not because of the simple aritmetic operation. It is because y use complex calculation to get an index. So adding a multiplication, an addition and 2 pair of parenthesis makes it even uglier. The point of this was to make code easier to read and mantain, but i think i'll stick with loop initialization.


This is why our benevolent emperor Mathematics gave us functions.

You never need write this arithmetic operation more than once in your entire codebase.

Sean Middleditch – Game Systems Engineer – Join my team!

What ^ said. If you want pretty code for the indexing logic, it's pretty easy to wrap around in a function.

You can also make a wrapper class that only contains the 1d vector and some methods or operator overloads. That'll allow you to write it like 2dArray.at(x, y) or even 2dArray(x, y).


template<class T> class Grid
{
public:
    Grid(int w, int h) : w(w), h(h), v(w * h) { }

    T &operator()(int x, int y){ return v[(y * w) + x]; }
    const T &operator()(int x, int y) const { return v[(y * w) + x]; }

    int width() const { return w; }
    int height() const { return h; }

private:
    int w, h;
    std::vector<T> v;
};

Or something like that...

Thank you very much for your answers.

As i mentioned in another post, what ia needed was an array of blocks(of fixed size).

The answers you gave actually works, but is there any actual difference between one aproch and another?(vector of vectors vs. vector+arithmetic index).

Thanks.

This topic is closed to new replies.

Advertisement