Как объединить два std::vector?
@FauChristian: Нет, с точки зрения эффективности это может быть бесполезно. Векторная память должна быть непрерывной, поэтому то, что вам предлагают, невозможно. Если вам нужно «какое-то сложное совместное использование управления узлами» и если вы измените класс векторов таким образом, вы получите двухстороннюю очередь. Даже в этом случае очень сложно повторно использовать память предложенным способом, хотя это станет немного более осуществимым. Я не думаю, что сейчас это реализовано. Главное, что при таком совместном использовании узлов управления (двухсторонней очереди) конечный узел может быть частично пустым.
@lecaruyer Вы понимаете, что только что отметили вопрос, который задавали два года назад, как дубликат
Я единственный, кто задается вопросом, почему это не реализовано как a + b или a.concat(b) в стандартной библиотеке? Возможно, реализация по умолчанию будет неоптимальной, но каждое объединение массивов не требует микрооптимизации.
годы эволюции, самая продвинутая перегрузка операторов из всех основных языков, система шаблонов, удваивающая сложность языка, и все же ответ - не v = v1 + v2;
Я предполагаю, что STL не хотел чрезмерно указывать язык на случай, если вы хотите, чтобы оператор делал что-то другое, например, добавляя векторы силы в физическую модель. В этом случае вы можете захотеть перегрузить forceVector1 + forceVector2, чтобы выполнить поэлементное добавление ясным и лаконичным кодом.
@ Spike0xff, v = v1 + v2 имеет значение в математике, которое не объединяется. К нему также предъявляются некоторые требования, чтобы его можно было вычислить. Я бы предпочел метод добавления (сокращение того, что можно сделать с помощью insert) или перегрузку push back.





Я бы использовал функция вставки, что-то вроде:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
Я бы только добавил код, чтобы сначала получить количество элементов, содержащихся в каждом векторе, и установить vector1 как самый большой. В противном случае вы делаете много ненужного копирования.
У меня есть вопрос. Будет ли это работать, если vector1 и vector2 - это одни и те же векторы?
Если у вас есть объединение нескольких векторов в один, полезно ли сначала вызвать reserve для вектора назначения?
@AlexanderRafferty: Только если vector1.capacity() >= 2 * vector1.size(). Что нетипично, если вы не позвонили в std::vector::reserve(). В противном случае вектор будет перераспределен, что сделает недействительными итераторы, переданные как параметры 2 и 3.
@FaheemMitha: Поскольку аргументы insert являются векторами, он уже знает, сколько элементов впереди, и будет обрабатывать его сам. Если мы вставляли другие вещи, такие как массив, было бы полезно сначала зарезервировать место.
@ Эйдин, я понимаю. Благодарю за разъяснение.
@Khaur: Это настолько ужасно, что в это трудно поверить. Для реализации очень легко обнаружить итераторы с произвольным доступом, вычислить размер и предварительно зарезервировать необходимое пространство. Я думаю, что MSFT делает это даже для прямых итераторов.
@MooingDuck Вы правы, я пропустил диспетчер и подумал, что версия итератора ввода применима ко всем типам итераторов. Версия с прямым итератором делает гораздо больше. Спасибо, что указали на это, я удалил свой первоначальный комментарий, чтобы он не появлялся без вашего.
Жаль, что в стандартной библиотеке нет более лаконичного выражения. .concat или += или что-то в этом роде
@nmr В C++ это довольно лаконично.
Трудно получить обзор всех различных ответов на этот вопрос. Подход std::vector::insert также был опубликован в нескольких других ответах, но у него больше всего голосов, поэтому я спрошу / заявлю здесь: использование insert должно иметь преимущество перед другими подходами, которые используют back_inserter, потому что insert потенциально может memcpy в одном объеме, в то время как подходы, использующие back_inserter, должны перебирать вектор, который нужно вставить, элемент за элементом. Я правильно понимаю?
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
Или вы можете использовать:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
Этот шаблон полезен, если два вектора не содержат в точности один и тот же тип объектов, потому что вы можете использовать что-то вместо std :: back_inserter для преобразования из одного типа в другой.
метод копирования - не такой уж хороший способ. Он будет вызывать push_back несколько раз, что означает, что если нужно вставить много элементов, это может означать несколько перераспределений. лучше использовать вставку, так как реализация вектора может сделать некоторую оптимизацию, чтобы избежать перераспределения. он может зарезервировать память перед началом копирования
@Yogesh: конечно, но ничто не мешает вам сначала вызвать в reserve. Причина, по которой std::copy иногда бывает полезна, заключается в том, что вы хотите использовать что-то другое, кроме back_inserter.
Когда вы говорите «множественные выделения», это правда - но в худшем случае количество выделений - это журнал (количество добавленных записей), что означает, что стоимость добавления записи постоянна в количестве добавленных записей. (В принципе, не беспокойтесь об этом, если профилирование не покажет, что вам нужен резерв).
Вместо этого вы можете использовать std :: transform.
копия - отстой, даже с запасом. vector :: insert позволит избежать всех проверок: quick-bench.com/bLJO4OfkAzMcWia7Pa80ynwmAIA
@DenisYaroshevskiy Разница в производительности разительная. Есть идеи, почему это происходит? Концептуально метод using_resize записывает пространство памяти res дважды, должно быть медленнее ??
@SamuelLi - в основном if > capacity_ в push_back, если проблема. Достаточно большой проблемы, что memset в resize не имеет значения.
Если вы используете 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 в конце.
Метод std :: make_move_iterator () помог мне при попытке объединить std :: vectors из std :: unique_ptr.
В чем разница между этим и std::move(src.begin(), src.end(), back_inserter(dest))?
@kshenoy, insert может выделить необходимый объем памяти за один ход. Когда back_inserter может привести к нескольким перераспределениям
Если вас интересует строгая гарантия исключения (когда конструктор копирования может вызвать исключение):
template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
const auto orig_v1_size = v1.size();
v1.reserve(orig_v1_size + v2.size());
try
{
v1.insert(v1.end(), v2.begin(), v2.end());
}
catch(...)
{
v1.erase(v1.begin() + orig_v1_size, v1.end());
throw;
}
}
Подобный append_move с сильной гарантией не может быть реализован в целом, если конструктор перемещения векторного элемента может бросать (что маловероятно, но все же).
Неужели на v1.erase(... тоже нельзя закинуть?
insert уже справляется с этим. Кроме того, этот вызов erase эквивалентен resize.
В C++ 11 я бы предпочел следующее, чтобы добавить вектор b к a:
std::move(b.begin(), b.end(), std::back_inserter(a));
когда a и b не перекрываются, и b больше не будет использоваться.
Это std::move от <algorithm>, а не обычныйstd::move от <utility>.
Неопределенное поведение, если a на самом деле равно b (что нормально, если вы знаете, что этого никогда не произойдет, но о нем стоит знать в коде общего назначения).
@MartinBonner Спасибо, что упомянули об этом. Возможно, мне следует вернуться к старому способу insert, который более безопасен.
просто добавьте следующую строку заголовка в начало: #include <iterator>
Ах, ДРУГОЙ std :: move. Довольно сбивает с толку в первый раз.
Это отличается от insert() с move_iterators? Если да, то как?
Я добавил примечание о том, о каком std::move мы говорим, поскольку большинство людей не знают об этой перегрузке. Надеюсь, это улучшение.
@Deqing Я не уверен, что вставка лучше ... Если a равно b, то, как только вы вставите несколько элементов, он перераспределит и аннулирует итераторы, переданные для вставки, которые затем будут продолжать использоваться, верно?
Добавьте это в свой заголовочный файл:
template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
vector<T> ret = vector<T>();
copy(a.begin(), a.end(), back_inserter(ret));
copy(b.begin(), b.end(), back_inserter(ret));
return ret;
}
и используйте его так:
vector<int> a = vector<int>();
vector<int> b = vector<int>();
a.push_back(1);
a.push_back(2);
b.push_back(62);
vector<int> r = concat(a, b);
r будет содержать [1,2,62]
Не знаю, почему это было отклонено. Возможно, это не самый эффективный способ сделать это, но он не неправильный и эффективный.
И это работает, если вы передаете один и тот же вектор в качестве обоих параметров, чтобы объединить вектор с самим собой.
Если то, что вы ищете, - это способ добавить один вектор к другому после создания, vector::insert - ваш лучший выбор, на что уже несколько раз ответили, например:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
К сожалению, нет никакого способа построить const vector<int>, как указано выше, вы должны сконструировать, а затем insert.
Если на самом деле вы ищете контейнер для объединения этих двух vector<int>, возможно, вам будет доступно что-то получше, если:
vector содержит примитивыconstЕсли все вышесказанное верно, я бы предложил использовать basic_string, char_type которого соответствует размеру примитива, содержащегося в вашем vector. Вы должны включить static_assert в свой код, чтобы эти размеры оставались согласованными:
static_assert(sizeof(char32_t) == sizeof(int));
С этим утверждением вы можете просто делать:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
Для получения дополнительной информации о различиях между string и vector вы можете посмотреть здесь: https://stackoverflow.com/a/35558008/2642059
Живой пример этого кода вы можете посмотреть здесь: http://ideone.com/7Iww3I
Я предпочитаю тот, который уже упоминался:
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());
}
std:: выводится через поиск, зависящий от аргументов. end(a) будет достаточно.
@Asu ADL добавит std:: только в том случае, если тип a исходит от std, что отменяет общий аспект.
хорошая точка зрения. в данном случае это вектор, так что он все равно будет работать, но да, это лучшее решение.
std :: begin () / end () были добавлены для коллекций (например, массивов), которые не имеют их в качестве функций-членов. Но у массивов также нет функции-члена insert (), и возникает вопрос: «Есть ли коллекция с insert (), но без begin () (которая работает с std :: begin ())?»
лучше не использовать резерв, так как это может повлечь за собой огромные накладные расходы. Смотрите здесь: stackoverflow.com/a/64102335/7110367
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
Хотя этот фрагмент кода может решить проблему, он не объясняет, почему и как он отвечает на вопрос. Пожалуйста, включите объяснение вашего кода, так как это действительно помогает улучшить качество вашего сообщения. Отметившие / обозреватели:Для ответов только с кодом, таких как этот, голос "против", не удаляйте! (Примечание: этот ответ может быть достаточно простым, чтобы дать объяснение и, следовательно, отрицательные голоса не нужны. Вы все равно можете добавить объяснение, чтобы предотвратить появление дополнительных флагов NAA / VLQ.)
Честно говоря, вы можете быстро объединить два вектора, скопировав элементы из двух векторов в другой или просто добавив только один из двух векторов !. Это зависит от вашей цели.
Способ 1: Присвойте новому вектору размер, равный сумме размеров двух исходных векторов.
vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector
Способ 2: Добавить вектор A путем добавления / вставки элементов вектора B.
// Loop for insert elements of vector_B into vector_A with insert()
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
Что ваш ответ добавляет, чего еще не было в других ответах?
@Mat: жирные символы.
Если после этого исходный вектор (-ы) больше не нужен, может быть лучше использовать std::move_iterator, чтобы элементы перемещались, а не копировались. (см. en.cppreference.com/w/cpp/iterator/move_iterator).
Что такое setcapacity? Что такое function: ?
@ L.F. Я думаю, он говорит о методе resize.
С диапазон v3 у вас может быть конкатенация ленивый:
ranges::view::concat(v1, v2)
Демо.
Я предполагаю, что это будет подходящий ответ примерно в 2023 году.
Вы должны использовать vector :: insert
v1.insert(v1.end(), v2.begin(), v2.end());
Разве это не то же самое с ответом, данным Томом Риттером и Робертом Гэмблом в 2008 году?
Вот решение общего назначения, использующее семантику перемещения C++ 11:
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector<T> result {};
result.reserve(lhs.size() + rhs.size());
result.insert(result.cend(), lhs.cbegin(), lhs.cend());
result.insert(result.cend(), rhs.cbegin(), rhs.cend());
return result;
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
if (lhs.empty()) return std::move(rhs);
lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return std::move(lhs);
}
Обратите внимание, чем это отличается от appending на vector.
общий прирост производительности для конкатенации - это проверка размера векторов. И объедините / вставьте меньший с большим.
//vector<int> v1,v2;
if (v1.size()>v2.size()) {
v1.insert(v1.end(),v2.begin(),v2.end());
} else {
v2.insert(v2.end(),v1.begin(),v1.end());
}
Так просто, но я никогда не думал об этом так!
Пример кода неверен. v1.insert(v2.end()... использует итератор в v2, чтобы указать позицию в v1.
Вы также можете использовать быструю замену. @DavidStone Я отредактировал его, чтобы можно было изменить порядок конкатенации. Можно ли добавить в начало вектора?
Вы можете вставить в начало, но это будет медленнее. Однако для истинной «конкатенации» порядок обычно имеет значение, так что это то, что вам нужно сделать.
Мне не нравится этот ответ, потому что вы не вставляете v2 после v1 во всех случаях (без указания этого примечания). В противном случае ваш ответ может быть более полным, если вы добавите решение, которое сохранит конкатенацию в другом векторе, а не изменит один из них.
Вы можете подготовить собственный шаблон для оператора +:
template <typename T>
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
Следующее - просто используйте +:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
Этот пример дает результат:
1 2 3 4 5 6 7 8
Использование T operator+(const T & a, const T & b) опасно, лучше использовать vector<T> operator+(const vector<T> & a, const vector<T> & b).
Это решение может быть немного сложным, но boost-range может предложить и другие приятные вещи.
#include <iostream>
#include <vector>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
boost::copy(b, std::back_inserter(a));
for (auto& iter : a) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
Часто намерение состоит в том, чтобы объединить вектор a и b, просто перебирая его, выполняя некоторую операцию. В данном случае - нелепая простая функция join.
#include <iostream>
#include <vector>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
std::vector<int> c = { 7,8,9 };
// Just creates an iterator
for (auto& iter : boost::join(a, boost::join(b, c))) {
std::cout << iter << " ";
}
std::cout << "\n";
// Can also be used to create a copy
std::vector<int> d;
boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
for (auto& iter : d) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
Для больших векторов это может быть преимуществом, поскольку отсутствует копирование. Его также можно использовать для простого копирования обобщений на более чем один контейнер.
Почему-то нет ничего похожего на boost::join(a,b,c), что могло бы быть разумным.
Если вы хотите иметь возможность кратко объединять векторы, вы можете перегрузить оператор +=.
template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
return vector1;
}
Тогда вы можете назвать это так:
vector1 += vector2;
Я реализовал эту функцию, которая объединяет любое количество контейнеров, переходя от rvalue-ссылок и копируя в противном случае
namespace internal {
// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
// Currently, require each homogenous inputs. If there is demand, we could probably implement a
// version that outputs a vector whose value_type is the common_type of all the containers
// passed to it, and call it ConvertingConcatenate.
static_assert(
std::is_same_v<
typename std::decay_t<Target>::value_type,
typename std::decay_t<Head>::value_type>,
"Concatenate requires each container passed to it to have the same value_type");
if constexpr (std::is_lvalue_reference_v<Head>) {
std::copy(head.begin(), head.end(), std::back_inserter(*target));
} else {
std::move(head.begin(), head.end(), std::back_inserter(*target));
}
if constexpr (sizeof...(Tail) > 0) {
AppendNoReserve(target, std::forward<Tail>(tail)...);
}
}
template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
if constexpr (sizeof...(Tail) > 0) {
return head.size() + TotalSize(tail...);
} else {
return head.size();
}
}
} // namespace internal
/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
size_t totalSize = internal::TotalSize(head, tail...);
std::vector<typename std::decay_t<Head>::value_type> result;
result.reserve(totalSize);
internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
return result;
}
Есть алгоритм std::merge из C++ 17, который очень легко использовать при сортировке входных векторов,
Ниже приведен пример:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
//DATA
std::vector<int> v1{2,4,6,8};
std::vector<int> v2{12,14,16,18};
//MERGE
std::vector<int> dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
//PRINT
for(auto item:dst)
std::cout<<item<<" ";
return 0;
}
Я не думаю, что его легче использовать, чем std::vector::insert, но он работает с чем-то другим: объединением двух диапазонов в новый диапазон против вставки одного вектора в конец другого. Стоит упомянуть в ответе?
В порядке. Я понял, чего ждут в ответе. Я добавлю.
Если ваша цель - просто перебрать диапазон значений только для чтения, альтернатива - обернуть оба вектора вокруг прокси (O (1)) вместо их копирования (O (n)), чтобы они были быстро видны. как единый, непрерывный.
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1)!
for (size_t i = 0; i < AB.size(); i++)
std::cout << AB[i] << " "; // ----> 1 2 3 4 5 10 20 30
Обратитесь к https://stackoverflow.com/a/55838758/2379625 для получения более подробной информации, включая реализацию VecProxy, а также плюсы и минусы.
Вы можете сделать это с помощью предварительно реализованных алгоритмов STL, используя шаблон для использования полиморфного типа.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){
for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
}
int main()
{
std::vector<int> values_p = {1,2,3,4,5};
std::vector<int> values_s = {6,7};
concat(values_p, values_s);
for(auto& it : values_p){
std::cout<<it<<std::endl;
}
return 0;
}
Вы можете очистить второй вектор, если не хотите его использовать в дальнейшем (метод clear()).
Соедините два std::vector-s с петлей for в один std::vector.
std::vector <int> v1 {1, 2, 3}; //declare vector1
std::vector <int> v2 {4, 5}; //declare vector2
std::vector <int> suma; //declare vector suma
for(int i = 0; i < v1.size(); i++) //for loop 1
{
suma.push_back(v1[i]);
}
for(int i = 0; i< v2.size(); i++) //for loop 2
{
suma.push_back(v2[i]);
}
for(int i = 0; i < suma.size(); i++) //for loop 3-output
{
std::cout << suma[i];
}
помимо того, что он не работает, этот код в значительной степени неидиоматичен. По крайней мере, вы должны использовать итераторы auto вместо ручной индексации. Вам не важно, какой индекс вы объединяете, только то, что это выполняется последовательно.
@TarickWelling Я не понимаю, почему вы сказали, что этот код не работает, не могли бы вы уточнить?
Вы проверяли дату моего комментария? Вы исправили ошибки в своем коде, теперь это просто не идиоматично.
Попробуйте создать два вектора и добавить второй вектор к первому вектору, код:
std::vector<int> v1{1,2,3};
std::vector<int> v2{4,5};
for(int i = 0; i<v2.size();i++)
{
v1.push_back(v2[i]);
}
v1: 1,2,3.
Описание:
Пока i int не имеет размера v2, отодвиньте элемент, индекс i в векторе v1.
Ваше описание нечеткое (и бесполезное, извините). В противном случае ваш ответ может быть более полным, если вы добавите второе решение, которое сохранит конкатенацию в другом векторе, а не изменит один из них.
Приведенные ответы на самом деле не объединяются. Они добавляют копию. Может быть использование (с точки зрения эффективности) для создания метода конкатенации std :: vector, однако это потребует некоторого сложного совместного использования управления узлами, и, вероятно, поэтому этого не было сделано.