Avatar ·

Как добавить один вектор в конец другого в C++ (append vector to vector)

Привет! Я только начал изучать C++ и STL. У меня есть два вектора, и я хочу добавить все элементы второго вектора в конец первого. Я перепробовал несколько способов, но ни один не работает так, как я ожидаю. Вот мой код: ```cpp #include #include int main() { std::vector vec1 = {1, 2, 3}; std::vector vec2 = {4, 5, 6}; // Пытаюсь добавить vec2 в vec1 vec1.append(vec2); // Ошибка: нет метода append // Пробую через insert vec1.insert(vec2.begin(), vec2.end()); // Ошибка компиляции // Пробую через push_back в цикле for (int i = 0; i < vec2.size(); i++) { vec1.push_back(vec2[i]); // Работает, но выглядит ужасно } return 0; } ``` Первый вариант вообще не компилируется, потому что у std::vector нет метода append. Второй вариант даёт ошибку, потому что insert ожидает итератор на позицию вставки, а я передаю только диапазон. Третий вариант работает, но мне кажется, что это неэффективно и некрасиво. В Python я просто писал vec1.extend(vec2), а в Java — vec1.addAll(vec2). Есть ли в C++ что-то подобное? Как правильно и эффективно добавить все элементы одного вектора в конец другого? Заранее спасибо! <<>>

Правильный способ: используйте перегрузку insert с итераторами

В C++ нет метода append для std::vector, но есть элегантное решение — метод insert с тремя аргументами: позиция вставки, начало диапазона и конец диапазона. Вы почти угадали, но ошиблись в синтаксисе. Вот правильный вариант:

#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;
}

Разберём по частям:

  • vec1.end() — это итератор, указывающий на позицию после последнего элемента vec1. Мы хотим вставлять именно туда.
  • vec2.begin() и vec2.end() — диапазон элементов, которые нужно скопировать из vec2.
  • Метод insert скопирует все элементы из диапазона [begin, end) в указанную позицию.

Почему это эффективно?

Стандартная реализация insert для диапазона итераторов обычно оптимизирована. Если новый размер вектора известен заранее, компилятор может зарезервировать память одной операцией. В отличие от цикла с push_back, который может вызывать множественные перераспределения памяти (каждый раз, когда ёмкость превышена).

Альтернатива: std::copy с std::back_inserter

Если вы предпочитаете алгоритмы STL, можно использовать std::copy:

#include <algorithm>
#include <iterator>

std::copy(vec2.begin(), vec2.end(), std::back_inserter(vec1));

Здесь std::back_inserter создаёт специальный итератор, который при присваивании вызывает push_back. Этот способ более универсален (работает с любыми контейнерами, поддерживающими push_back), но менее нагляден.

Современный C++17/20: std::vector::insert_range (C++23)

В C++23 появится метод insert_range, который делает то же самое более читаемо:

// Только C++23 и новее
vec1.insert_range(vec1.end(), vec2);

Но пока большинство компиляторов не поддерживают C++23, используйте insert с итераторами.

Важное замечание про производительность

Если вы добавляете много векторов или работаете с большими данными, рекомендуется заранее зарезервировать память:

vec1.reserve(vec1.size() + vec2.size());
vec1.insert(vec1.end(), vec2.begin(), vec2.end());

Это гарантирует, что не будет лишних перераспределений памяти.

Итог

Лучший способ добавить один вектор в конец другого в C++ — использовать vec1.insert(vec1.end(), vec2.begin(), vec2.end()). Это кратко, эффективно и соответствует идиоматике STL.

<<>>

Использование std::merge для объединения двух отсортированных векторов

Если ваши векторы уже отсортированы и вы хотите получить отсортированный результат, std::merge будет идеальным решением:

#include <algorithm>
#include <vector>

std::vector<int> vec1 = {1, 3, 5};
std::vector<int> vec2 = {2, 4, 6};
std::vector<int> result;

result.reserve(vec1.size() + vec2.size());
std::merge(vec1.begin(), vec1.end(), 
           vec2.begin(), vec2.end(), 
           std::back_inserter(result));
// result = {1, 2, 3, 4, 5, 6}

Дополнение: перемещение элементов (C++11 и новее)

Если второй вектор больше не нужен, можно переместить его элементы, избежав копирования:

vec1.insert(vec1.end(), 
            std::make_move_iterator(vec2.begin()), 
            std::make_move_iterator(vec2.end()));

После этой операции vec2 останется в корректном, но неопределённом состоянии (обычно пустым). Это особенно полезно для векторов с "тяжёлыми" объектами, где копирование дорого.

Когда использовать цикл?

Цикл с push_back оправдан, если вам нужно добавить только часть элементов или выполнить дополнительную обработку каждого элемента перед вставкой. Но для простого добавления всего вектора используйте insert с итераторами — это идиоматичный способ в C++.