Reputation: 1026
Suppose I want to represent a two-dimensional matrix of int
as a vector of vectors:
std::vector<std::vector<int> > myVec;
The inner dimension is constant, say 5, and the outer dimension is less than or equal to N
. To minimize reallocations I would like to reserve space:
myVec.reserve(N);
What size is assumed for the inner vector? Is this purely implementation dependent? How does this effect the spatial locality of the data? Since the inner dimension is a constant is there a way to tell the compiler to use this constant size? How do these answers change if the inner vector's size changes?
Upvotes: 35
Views: 31073
Reputation: 283961
Since your inner dimension is constant, I think you want
std::vector< std::array<int, 5> > vecs;
vecs.reserve(N);
This will give you preallocated contiguous storage, which is optimal for performance.
Upvotes: 23
Reputation: 26356
The inner vectors are initialized with the default constructor. So if you write:
vector<vector<int> > vecs;
vecs.reserve(10);
This is equivalent to calling the constuctor of vector<int>
or vector<int>()
for each element. Which means you'll have a zero-sized vectors. But remember, you can't use them unless you resize (not reserve) your vectors.
Remember, too, that it could be sometimes more efficient to resize with the initial size that you would need. So it's useful to do something like
vector<vector<int> > vecs(3,vector<int>(5));
This will create a vector with size 3, and each element will contain a vector of size 5.
Remember also, that it could be more efficient to use deque rather than vector if you're going to resize your vectors often. They're easy to use (as vectors) and you don't need to reserve, since the elements are not contiguous in memory.
Upvotes: 16
Reputation: 16263
The size of the inner vectors is completely irrelevant for resizing the outer vector. There are no locality guarantees for your bundle of vectors, the locality guarantee (i.e. contiguous block in memory) exists for a single vector only.
Remember that a vector object itself has constant sizeof
-size, its actual data is usually dynamically allocated. The outer vector, to first approximation, is a contiguous block of N 'pointers' to the inner vectors. Your reserve
call does not reserve memory for possible elements of inner vectors, but only for the inner vector objects themselves (i.e. their bookkeeping data and their pointers to their dynamically allocated data block).
Upvotes: 15