Ответ 1
Существует несколько способов создания vector
с элементами n
:
ctor + по умолчанию push_back
(неоптимальный)
std::vector<Entry> phone_book;
for (std::size_t i = 0; i < n; ++i) {
phone_book.push_back(entry);
}
Это имеет тот недостаток, что при перемещении элементов происходит перераспределение. Это означает выделение памяти, перемещение элементов (или копирование, если они не могут быть перемещены или для pre c ++ 11) и освобождение памяти (с уничтожением объекта). Скорее всего, это произойдет более одного раза для n
прилично большого. Стоит отметить, что для push_back
гарантированная "амортизированная постоянная" означает, что он не будет перераспределяться после каждого push_back
. Каждое перераспределение будет увеличивать размер геометрически. Далее читайте: стратегия перераспределения std::vector и std::string
Используйте это, если вы не знаете размер заранее, и у вас даже нет приблизительной оценки размера.
"подсчитать количество вставленных по умолчанию экземпляров T" ctor с последующими назначениями (не рекомендуется)
std::vector<Entry> phone_book(n);
for (auto& elem : phone_book) {
elem = entry;
}
Это не требует перераспределения, но все элементы n
будут изначально созданы по умолчанию, а затем скопированы для каждого нажатия. Это большой недостаток, и влияние на производительность будет измеримым. (это менее заметно для основных типов).
Не используйте это, поскольку есть лучшие альтернативы для почти каждого сценария.
cort "количество копий элементов" (рекомендуется)
std::vector<Entry> phone_book(n, entry);
Это лучший метод для использования. Поскольку вы предоставляете всю информацию, необходимую в конструкторе, он сделает наиболее эффективное распределение + назначение. Это может привести к появлению кода без ответвлений с векторизованными инструкциями для назначений, если Entry
имеет тривиальный конструктор копирования.
ctor по умолчанию + reserve
+ push_back
(рекомендуется ситуационная ситуация)
vector<Entry> phone_book;
phone_book.reserve(n);
for (std::size_t i = 0; i < n; ++i) {
phone_book.push_back(entry);
}
Перераспределение не произойдет, и объекты будут построены только один раз. Лучшим выбором для push_back
может быть emplace_back
.
Используйте это, если у вас есть приблизительное приближение размера. Предпочитайте большее предположение, а не низкое), и в конце вы можете использовать shrink_to_fit
.
Используйте это, если не все элементы одинаковы, например:
Entry make_entry(std::size_t i);
std::vector<Entry> phone_book;
phone_book.reserve(n);
for (std::size_t i = 0; i < n; ++i) {
phone_book.push_back(make_entry(i));
}
стандартные ctor + std::fill_n
и std::back_inserter
(рекомендуется ситуационная ситуация)
#include <algorithm>
#include <iterator>
std::vector<Entry> phone_book;
std::fill_n(std::back_inserter(phone_book), n, entry);
Это в значительной степени <algorithm>
версия reserve
+ push_back
.
Используйте это, если вам нужно заполнить вектор после его определения
ctor + по умолчанию std::generate_n
и std::back_inserver
(для разных объектов entry
)
Entry entry_generator();
std::vector<Entry> phone_book;
std::generate_n(std::back_inserter(phone_book), n, [] { return entry_generator(); });
Вы можете использовать это, если каждый entry
отличается и получен из генератора, где вы не меняете параметры.