9
votes

I like to reserve memory for the inner vector in a std::vector<std::vector<TYPE>>, in order to avoid a lot of single memory allocations during a subsequent push_back. I don't know the innerSize of the vector exactly, but I can give a good estimate.

std::resize can be used as

vecs.resize(outerSize, std::vector<TYPE>(innerSize));

where outerSize and innerSize are given ints. This does not work for me, because the default constructor is not applicable. However std::reserve does not provide an interface like this.

Is this a good way to reserve memory for all inner vectors?

vecs.resize(outerSize);
for (auto &elem : vecs) {
    elem.reserve(innerSize);
}
2
Yes, that is a good way. - Chris Drew
Your loop seems the better way. I even think that vecs.resize(outerSize, vector_with_reserved_size); is not guaranty to build inner vectors with correct capacity. - Jarod42
Note that vecs.resize(outerSize, std::vector<TYPE>(innerSize)); is very different than the reserve loop you have. The former will initialize every inner vector with the default constructor. If TYPE is large, it will end up taking much longer time than the reserve loop. EDIT: And later on you'd have to replace existing TYPE items, instead of calling push_back. - Edy

2 Answers

5
votes

The only alternative that I can think of is that you create a wrapper class around the inner std::vector; which reserves it on construction. Leading to something like

struct TableRow {
    std::vector<TYPE> data;
    TableRow() {
        data.reserve(SIZE);
    }
}

std::vector<TableRow> myVectorOfVectors;

The other gain from this is that your inner vector gets a name that you can understand (such as TableRow); but the downside is that unless you're willing to play the game of inheriting std::vector (if in doubt; don't do this); your usage of the wrapper class will have to be a little awkward since you'll need to add a .data or something of that ilk.

As others have said though; your way is perfectly fine.

3
votes

Yes, your attempt is a good solution, if not the best:

#include <vector>

std::vector<std::vector<NonDefaultConstructible>> vecs;
vecs.resize(outerSize);
for (auto &elem : vecs) {
    elem.reserve(innerSize);
}

The only way to improve it would need a constructor for std::vector which would accept a capacity and construct a vector with size zero and provided capacity. Such a constructor does not exist.