Конкатенация двух стандартных: векторов - PullRequest
579 голосов
/ 14 октября 2008

Как объединить два std::vector с?

Ответы [ 18 ]

635 голосов
/ 14 октября 2008
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
152 голосов
/ 23 февраля 2014

Если вы используете C ++ 11 и хотите переместить элементы, а не просто скопировать их, вы можете использовать std::move_iterator вместе со вставкой (или копией):

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<int> dest{1,2,3,4,5};
  std::vector<int> src{6,7,8,9,10};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  // Print out concatenated vector.
  std::copy(
      dest.begin(),
      dest.end(),
      std::ostream_iterator<int>(std::cout, "\n")
    );

  return 0;
}

Это не будет более эффективно для примера с целочисленными значениями, поскольку перемещение их не более эффективно, чем их копирование, но для структуры данных с оптимизированными перемещениями можно избежать копирования ненужного состояния:

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
  std::vector<std::vector<int>> src{{6,7,8,9,10}};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  return 0;
}

После перемещения элемент src остается в неопределенном, но безопасном для уничтожения состоянии, а его прежние элементы передаются непосредственно новому элементу dest в конце.

131 голосов
/ 14 октября 2008

Я бы использовал функцию вставки , что-то вроде:

vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
75 голосов
/ 14 октября 2008

Или вы можете использовать:

std::copy(source.begin(), source.end(), std::back_inserter(destination));

Этот шаблон полезен, если два вектора не содержат абсолютно одинаковую вещь, потому что вы можете использовать что-то вместо std :: back_inserter для преобразования одного типа в другой.

48 голосов
/ 12 июня 2015

С C ++ 11 я бы предпочел добавить вектор b к a:

std::move(b.begin(), b.end(), std::back_inserter(a));

, когда a и b не перекрываются, и b больше не будет использоваться.


Это std::move от <algorithm>, а не обычный std::move от <utility>.

31 голосов
/ 14 октября 2008
std::vector<int> first;
std::vector<int> second;

first.insert(first.end(), second.begin(), second.end());
22 голосов
/ 10 июня 2016

Я предпочитаю тот, который уже упоминался:

a.insert(a.end(), b.begin(), b.end());

Но если вы используете C ++ 11, есть еще один общий способ:

a.insert(std::end(a), std::begin(b), std::end(b));

Кроме того, это не часть вопроса, но желательно использовать reserve перед добавлением для повышения производительности. И если вы соединяете вектор с самим собой, без резервирования он потерпит неудачу, поэтому вы всегда должны reserve.


Так что в основном то, что вам нужно:

template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}
12 голосов
/ 08 августа 2017

Вы должны использовать vector :: insert

v1.insert(v1.end(), v2.begin(), v2.end());
9 голосов
/ 08 августа 2017

При диапазоне v3 , вы можете иметь ленивое объединение:

ranges::view::concat(v1, v2)

Демо .

5 голосов
/ 08 мая 2018

A общее повышение производительности для сцепления - проверка размера векторов. И объединить / вставить меньший с большим.

//vector<int> v1,v2;
if(v1.size()>v2.size()){
    v1.insert(v1.end(),v2.begin(),v2.end());
}else{
    v1.insert(v2.end(),v1.begin(),v1.end());
}
...