Резервирование пространства для двойного вектора - PullRequest
0 голосов
/ 27 апреля 2019

Предположим, T - это тип, и я хочу сделать vector<vector<T>>. Я знаю, что конечный размер будет m x n, где m и n - константы времени выполнения. (Если бы они были константами времени компиляции, я бы использовал std::array<std::array<T, n>, m>.) Предположим, у меня есть три варианта действий с моим двойным вектором, прежде чем я продолжу серьезно заниматься своей программой:

Вариант 1

std::vector<std::vector<T>> dbl_vect(m);
for (auto & v : dbl_vect)
    v.reserve(n);

Вариант 2

std::vector<std::vector<T>> dbl_vect;
dbl_vect.reserve(m);

Вариант 3

std::vector<std::vector<T>> dbl_vect;

Предположим, меня не беспокоит аннулирование итераторов и ссылок из перераспределения векторов, поэтому мы можем удалить это из процесса принятия решения.

Конечно, следующий за этим код должен был бы быть немного другим, так как # 1 создает (пустые) строки dbl_vector, поэтому мы должны получить доступ к строкам, а не толкать больше назад.

Вариант № 2 кажется довольно бесполезным, потому что он не знает, сколько места зарезервировать для каждой строки.

Опция # 1 требует, чтобы я проходил линейный проход m пустых векторов и изменял их размер вручную, но это предотвращает перераспределение. Я думаю, что если бы T было довольно большим, это почти наверняка было бы предпочтительнее, потому что это предотвратило бы копирование / перемещение.

Вопрос: Допустим, T = char (или выберите свой любимый тип POD). При каких обстоятельствах я должен быть безразличен между вариантами 1 и 3 или даже предпочесть № 3? Это в основном из-за относительно небольшого размера char или из-за того, что компилятор (не) по умолчанию инициализирует char? Если T больше, может быть, определяется пользователем, в какой момент (по размеру двойного вектора или по размеру T) мне следует начать заботиться?

Здесь задается несколько похожий вопрос относительно одного вектора и T=int.

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Если вы знаете, что внутренний размер будет m, можно сделать std::vector<S>, где S - ваш пользовательский тип, обозначающий std::vector<T>, за исключением того, что он знает, сколько записей у него будет. Аналогичное решение предлагается здесь (кроме случаев, когда m - это константа времени компиляции).

0 голосов
/ 27 апреля 2019

# 3 просто по умолчанию инициализирует вектор.Вы ничего не получите от этого, поскольку содержащий вектор будет иметь нулевую емкость.Динамическое распределение памяти происходит медленно, поэтому, чтобы минимизировать это, я бы всегда использовал # 1 или его вариант.

...