简体   繁体   中英

Memory taken by a vector of vectors

What is the expected difference (if any) in memory taken by vvint1 and vvint2 ? Is vitest1 copied into a new memory position each time a push_back takes place? Is vitest2 copied into a new memory position each time a push_back takes place?

typedef vector<int> vint_t;
typedef vector<vint_t> vvint_t;
size_t nvec = 2;
size_t nvvec = 3;
vvint_t vvint1(nvvec), vvint2(nvvec);
vint_t vitest2(nvec, 1);
for ( j = 0; j < nvvec; j++ ) {
    vint_t vitest1(nvec, 2);
    vvint1.push_back(vitest1);
    vvint2.push_back(vitest2);
}

Both vvint1 and vvint2 are initially created with nvvec = 3 default-constructed members (ie empty vectors of int).

push_back always either copies or moves, but in this case you're not supplying rvalue references so you'll get copies. Look into std::move for more on that.

You're pushing the same number of things to both vectors. Therefore both vvint1 and vvint2 will end up being the same size.

vvint1 and vvint2 memory requirements are:

  1. (on stack, in the example) sizeof(vector<vector<int>>) for the objects themselves, which is the same ( vector is 2–3 pointers usually, regardless of the inner type);
  2. (on heap) 2 * nvvec * sizeof(vector<int>) for the contents ( nvvec initially and nvvec push_back -ed in the loop); again, that's the same for vvint1 and vvint2 ;
  3. (on heap) contents of each vector stored in these vectors. Since vectors don't share memory, and you store them by value, nvec * nnvec * sizeof(int) . Again, the same.

So the overall requirements are the same: sizeof(vector<vector<int>>) + nvvec * sizeof(vector<int>) + nvec * nnvec * sizeof(int)

Plain vector<int> would take less space ofc as item 2 wouldn't apply. But what is more important is that in vvint_t , inner vectors may be of different lengths, and resizing any inner vector doesn't affect others. But that adds complexity, so unless you really need that, it's simpler to use flat vector and calculate index; imaging libraries do it that way.

Regarding second part, both vitest s are copied on each push_back. But since C++11, you can write vvint1.push_back(std::move(vitest1)); (or vvint1.emplace_back(std::move(vitest1)); ) to move instead. For vectors that means the newly-constructed vector takes ownership of vitest1 contents without copying it (so vitest1 becomes empty). That doesn't change memory requirements but reduces allocations as the space allocated by vitest (at construction) would be reused instead of being freed (at destruction, at end of each iteration).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM