Я относительно новичок в С++ и пытался провести некоторое исследование, но при поиске в Интернете я в основном сталкивался с массивами C, а не с std::array
. Каковы наиболее эффективные способы добавления элементов std::array в std::vector и вставки элементов std::array
в std::vector
? Должен ли я использовать функции STL, такие как std::copy
? В настоящее время я использую С++ 17, MinGW64.
Как добавить или вставить элементы std::array в std::vector?
Ответы (2)
Добавление значений может означать две вещи: вы либо хотите копировать/дублировать рассматриваемые элементы, либо они вам не нужны в исходном контейнере, и вы также можете переместить их в целевой контейнер. Кроме того, имеет смысл различать вставку во время создания и добавление к существующему, уже созданному контейнеру: если вы можете, всегда создавайте контейнер с элементами, которыми он должен владеть.
Скопируйте и добавьте
std::array
элементов в уже созданныйstd::vector
:std::vector<T> dest; std::array<T, N> source; // ... dest.insert(dest.end(), source.cbegin(), source.cend());
Переместите-добавьте
std::array
элементов к уже построенномуstd::vector
.std::vector<T> dest; std::array<T, N> source; // ... dest.insert(dest.end(), std::move_iterator(source.begin()), std::move_iterator(source.end()));
Скопируйте
std::array
элементов вstd::vector
при построении:std::array<T, N> source; // ... std::vector<T> dest(source.cbegin(), source.cend());
Переместите
std::array
элементов вstd::vector
при построении:std::array<T, N> source; // ... std::vector<T> dest(std::move_iterator(source.begin()), std::move_iterator(source.cend()));
Здесь нечего добавить, говоря о вставке в середину — единственная заметная разница в том, что она всегда будет менее эффективной, так как оставшиеся элементы в месте назначения std::vector
будут построены путем перемещения (что составляет O (N)).
Также обратите внимание, что для добавления элементов есть std::move
и std::copy
из заголовка <algorithm>
(где std::copy
можно использовать с std::move_iterator
s). Однако они не могут быть такими же эффективными, как прямой вызов std::vector::insert
, потому что первый работает с абстракцией итератора и обрабатывает копирование/перемещение по одному элементу за раз, не зная сведений о хранилище места назначения (это может привести к многократному изменению размеров буфера). ), в то время как последняя является функцией-членом std::vector
и изменит размер буфера только один раз (при необходимости).
Чтобы добавить элементы существующего массива (или другого диапазона в целом) к вектору, вы можете просто использовать перегрузку вставки вектора для диапазона итератора:
vector<int> vec{1, 2, 3};
array<int, 3> arr{4, 5, 6};
// arr could be some other container or bare array as well, for ex.:
// int arr[] = {4, 5, 6};
// vector<int> arr {4, 5, 6};
// list<int> arr {4, 5, 6};
// ...
vec.insert(vec.end(), begin(arr), end(arr)); // insert at vec.end() = append
//or vec.insert(vec.end(), arr.begin(), arr.end()); // insert at vec.end() = append
Обратите внимание: если у вас есть какой-то другой тип вместо int
, который дорого копировать, и вы хотите переместить элементы из исходного массива, вы можете использовать move_iterator
, например .
vec.insert(vec.end(), move_iterator(arr.begin()), move_iterator(arr.end()));
Для операций с диапазонами в целом функции-члены контейнера предпочтительнее вместо одноименных функций из заголовка <algorithm>
.
Так, например, в этом случае vec.insert
вставит диапазон сразу, в отличие от std::insert
, где элементы будут вставлены один за другим.
Это очень хорошо объясняется в Effective STL Скотта Мейерса.