0

In a C++ class called ClassA, I had previously an attribute of type double dimension array of another class called ClassB:

private: ClassB matrix[ROWS][COLS];

where ROWS and COLS where static values.

I am now modifying the application to be able to specify the two dimensions on command line. I am thinking about using a vector<vector<ClassB>> instead. Before moving to this solution, I am wondering how such an object will be initialized by default. vector attributes are automatically allocated, but what will happen with the nested vectors ? Should I allocate them myself ?

NOTE: I was not able to find the answer to this question, so please let me know if it's a duplicate.

Manuel Selva
  • 18,554
  • 22
  • 89
  • 134

1 Answers1

2

The default constructor of std::vector<std::vector> will construct the vector of vectors, but absolutely no memory will be allocated for its elements (in this case the inner vectors), unless you explicitly say so. If you need to allocate memory corresponding to ROWS x COLS, use e.g.

std::vector<std::vector<int>> vec(ROWS, std::vector<int>(COLS));

If you just say

std::vector<std::vector<int>> vec(ROWS);

then ROWS elements of the outer vector will be default-constructed, hence no memory will be allocated for the inner vectors, and you'd have to manually reserve each one or push_back into them.

The constructors of std::vector are defined in all their glory here.

But in general it is a bad idea to use nested vectors, since you lose the locality of data, and the code may be slower. In other words, there is no guarantee that the data will be contiguous in memory. A vector<vector> is storing the data internally as an array of pointers, and while the pointers are stored contiguously, each chunk of data they point to is not guaranteed to be adjacent in memory. It is better to use a "flatten" vector and translate from 2D to 1D and vice-versa.

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • Beware, that if `T` is something more complex than `int`, then `T`s constructor will be called. – Zereges Oct 05 '15 at 20:52
  • @Zereges Yes, the default constructor of the element is called. – vsoftco Oct 05 '15 at 20:54
  • Thank you for the very fast answer. should I do the allocation you mention inside the constructor of my ClassA ? Does the T constructor will be called even if nested vectors size is 0 as in this example ? – Manuel Selva Oct 05 '15 at 20:58
  • Arf, 0 is the initial value, not the size ! i am tired – Manuel Selva Oct 05 '15 at 20:59
  • @ManuelSelva If you know for sure that the outer vectors are all of size `COLS`, then yes, you can do something like: `struct ClassA { std::vector> vec; ClassA(): vec(ROWS, std::vector(COLS)){} };` And also if the initial value is `0`, you don't need to explicitly specify it. The default constructor of the type will value-initialize it to `0`. – vsoftco Oct 05 '15 at 21:04
  • @vsoftco Thank you again. I am now seeing that the class I want to put in my vector of vector is abstract :) – Manuel Selva Oct 05 '15 at 21:07
  • @ManuelSelva Then you have a problem :) – vsoftco Oct 05 '15 at 21:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/91426/discussion-between-manuel-selva-and-vsoftco). – Manuel Selva Oct 05 '15 at 21:11