Память занята вектором векторов - PullRequest
0 голосов
/ 26 февраля 2020

Какова ожидаемая разница (если есть) в памяти, занятая vvint1 и vvint2? Копируется ли vitest1 в новую позицию памяти каждый раз, когда происходит push_back? vitest2 копируется в новую позицию памяти каждый раз, когда происходит push_back?

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);
}

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

И vvint1, и vvint2 изначально создаются с nvvec = 3 сконструированными по умолчанию элементами (т.е. пустыми векторами типа int).

push_back всегда либо копирует, либо перемещает, но в этом случае вы Вы не предоставляете ссылки на rvalue, поэтому вы получите копии. Подробнее об этом смотрите std::move.

Вы добавляете одинаковое количество вещей к обоим векторам. Поэтому и vvint1, и vvint2 будут иметь одинаковый размер.

0 голосов
/ 26 февраля 2020

vvint1 и vvint2 требования к памяти:

  1. (в стеке, в примере) sizeof(vector<vector<int>>) для самих объектов, то же самое (vector равно 2– Обычно 3 указателя, независимо от внутреннего типа);
  2. (в куче) 2 * nvvec * sizeof(vector<int>) для содержимого (nvvec первоначально и nvvec push_back -ed в l oop); опять же, это то же самое для vvint1 и vvint2;
  3. (в куче) содержимого каждого вектора, хранящегося в этих векторах. Поскольку векторы не разделяют память, а вы сохраняете их по значению, nvec * nnvec * sizeof(int). Опять то же самое.

Таким образом, общие требования одинаковы: sizeof(vector<vector<int>>) + nvvec * sizeof(vector<int>) + nvec * nnvec * sizeof(int)

Обычный vector<int> займет меньше места c, так как пункт 2 не будет применяться , Но что более важно, это то, что в vvint_t внутренние векторы могут иметь разную длину, и изменение размера любого внутреннего вектора не влияет на другие. Но это добавляет сложности, поэтому, если вам это действительно не нужно, проще использовать плоский вектор и рассчитать индекс; библиотеки изображений делают это таким образом.

Что касается второй части, то оба vitest s копируются на каждый push_back. Но начиная с C ++ 11, вы можете написать vvint1.push_back(std::move(vitest1)); (или vvint1.emplace_back(std::move(vitest1));) для перемещения. Для векторов это означает, что вновь созданный вектор становится владельцем содержимого vitest1 без его копирования (поэтому vitest1 становится пустым). Это не меняет требований к памяти, но уменьшает распределение, так как пространство, выделенное vitest (при создании), будет использоваться повторно вместо освобождения (при уничтожении, в конце каждой итерации).

...