Как добавить один вектор в конец другого вектора в C++?
Правильный способ: метод insert с итераторами
Вы почти угадали с insert. Ошибка в том, что вы передавали сам объект vec2, а нужно передать диапазон элементов из него с помощью итераторов. Вот правильный синтаксис:
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5, 6};
// Добавляем все элементы vec2 в конец vec1
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
// Результат: vec1 = {1, 2, 3, 4, 5, 6}
for (int x : vec1) {
std::cout << x << " ";
}
return 0;
}
Как это работает
Метод insert имеет перегрузку, принимающую три аргумента:
- Позиция вставки — итератор, указывающий на место, куда вставлять.
vec1.end()означает "в самый конец". - Начало диапазона — итератор на первый элемент источника (
vec2.begin()). - Конец диапазона — итератор на элемент, следующий за последним (
vec2.end()).
Таким образом, вы копируете все элементы из одного вектора в другой. Это стандартный идиоматичный способ конкатенации в C++.
Альтернатива: std::copy с std::back_inserter
Другой популярный способ — использовать алгоритм std::copy в паре с итератором вставки:
#include <algorithm> // для std::copy
#include <iterator> // для std::back_inserter
std::copy(vec2.begin(), vec2.end(), std::back_inserter(vec1));
std::back_inserter создает специальный итератор, который при присваивании вызывает push_back. Этот метод более гибкий, если вам нужно вставлять элементы не только в конец.
Производительность и перемещение (C++11 и новее)
Если после копирования исходный вектор (vec2) вам больше не нужен, можно использовать семантику перемещения, чтобы избежать лишних копирований тяжелых объектов (например, std::vector<std::string>):
#include <utility> // для std::make_move_iterator
vec1.insert(vec1.end(),
std::make_move_iterator(vec2.begin()),
std::make_move_iterator(vec2.end()));
// После этой операции vec2 находится в "пустом", но корректном состоянии.
std::make_move_iterator оборачивает обычные итераторы в move-итераторы, которые при копировании перемещают элементы вместо копирования. Это значительно ускоряет работу с большими данными.
Итог
Для простого добавления используйте vec1.insert(vec1.end(), vec2.begin(), vec2.end()). Если нужна максимальная производительность и vec2 больше не нужен — используйте std::make_move_iterator. Избегайте ручных циклов — STL предоставляет все необходимые инструменты для чистого и эффективного кода.
Использование std::vector::reserve для оптимизации
Коллега выше правильно описал основной способ. Я хочу добавить важный момент про производительность. Когда вы вызываете insert или std::copy с back_inserter, вектор может перераспределять свою внутреннюю память несколько раз по мере роста. Если вы заранее знаете итоговый размер, можно избежать этого и ускорить код в 2-3 раза:
#include <vector>
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5, 6};
// Резервируем память под будущие элементы
vec1.reserve(vec1.size() + vec2.size());
// Теперь вставка не вызовет перераспределений
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
Когда это важно
Это критично, если вы объединяете векторы в цикле или работаете с большими объемами данных (миллионы элементов). Без reserve каждый раз, когда вектору не хватает памяти, он выделяет новый блок, копирует (или перемещает) все старые элементы и удаляет старый блок — это дорогостоящая операция.
Также обратите внимание: reserve только выделяет память, но не меняет размер вектора. Размер изменится только после вставки. Это безопасно и не влияет на логику программы.
Таким образом, золотое правило: "сначала reserve, потом insert" для максимальной эффективности.
Ответов пока нет.
Войдите чтобы оставить ответ