Как добавить или вставить элементы std::array в std::vector?

Я относительно новичок в С++ и пытался провести некоторое исследование, но при поиске в Интернете я в основном сталкивался с массивами C, а не с std::array. Каковы наиболее эффективные способы добавления элементов std::array в std::vector и вставки элементов std::array в std::vector? Должен ли я использовать функции STL, такие как std::copy? В настоящее время я использую С++ 17, MinGW64.


person ZzXNSZD    schedule 08.02.2021    source источник


Ответы (2)


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

  1. Скопируйте и добавьте std::array элементов в уже созданный std::vector:

    std::vector<T> dest;
    std::array<T, N> source;
    
    // ...
    
    dest.insert(dest.end(), source.cbegin(), source.cend());
    
  2. Переместите-добавьте 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()));
    
  3. Скопируйте std::array элементов в std::vector при построении:

    std::array<T, N> source;
    
    // ...
    
    std::vector<T> dest(source.cbegin(), source.cend());
    
  4. Переместите 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_iterators). Однако они не могут быть такими же эффективными, как прямой вызов std::vector::insert, потому что первый работает с абстракцией итератора и обрабатывает копирование/перемещение по одному элементу за раз, не зная сведений о хранилище места назначения (это может привести к многократному изменению размеров буфера). ), в то время как последняя является функцией-членом std::vector и изменит размер буфера только один раз (при необходимости).

person lubgr    schedule 08.02.2021

Чтобы добавить элементы существующего массива (или другого диапазона в целом) к вектору, вы можете просто использовать перегрузку вставки вектора для диапазона итератора:

   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 Скотта Мейерса.

Текущий

person StPiere    schedule 08.02.2021
comment
Обратите внимание, что это точно так же, как можно добавить элементы голого массива в вектор или элементы связанного списка, если на то пошло. Подойдет любой диапазон ввода. - person eerorika; 08.02.2021
comment
Также можно использовать итераторы перемещения, в зависимости от типа. - person Ayxan Haqverdili; 08.02.2021