Question

How to Concatenate Two std::vector Objects in C++

cppconcatenationstdstdvector

Question

I want to combine the contents of two std::vector objects into one in C++. What is the correct and efficient way to concatenate two vectors?

Short Answer

By the end of this page, you will understand how to concatenate two std::vector objects in C++, when to use insert, how to avoid unnecessary copies, and what common mistakes to watch for when combining vectors.

Concept

std::vector is a dynamic array in C++ that stores elements in contiguous memory. Concatenating two vectors means taking all elements from one vector and appending them to the end of another.

In C++, there is no built-in + operator for std::vector in the standard library. Instead, developers usually concatenate vectors by using member functions such as insert.

This matters because concatenating collections is very common in real programs:

  • merging results from multiple functions
  • combining filtered data sets
  • building a final list from smaller parts
  • appending batches of records before processing

The most common and idiomatic approach is:

v1.insert(v1.end(), v2.begin(), v2.end());

This appends all elements from v2 to the end of v1.

A key detail is that vectors may need to reallocate memory when they grow. If you know the final size in advance, calling reserve first can improve performance by reducing reallocations.

Mental Model

Think of a std::vector like a row of numbered boxes on a shelf.

  • v1 is your first row of boxes.
  • v2 is a second row of boxes.
  • Concatenation means taking every box from v2 and placing copies of them at the end of v1.

If the shelf for v1 is too small, C++ may build a bigger shelf, move the old items over, and then add the new ones. That is why reserving enough space ahead of time can help.

Take Quiz

Syntax and Examples

Basic syntax

v1.insert(v1.end(), v2.begin(), v2.end());

This means:

  • start inserting at the end of v1
  • take elements from v2.begin() up to v2.end()
  • append them to v1

Example

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v1 = {1, 2, 3};
    std::vector<int> v2 = {4, 5, 6};

    v1.insert(v1.end(), v2.begin(), v2.end());

    for (int n : v1) {
        std::cout << n << ' ';
    }
}

Output:

1 2 3 4 5 6

With reserve for better performance

#include <vector>

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {4, 5, 6};

v1.reserve(v1.size() + v2.size());
v1.insert(v1.end(), v2.begin(), v2.end());

This can avoid extra memory reallocations.

Creating a new concatenated vector

If you do not want to modify either original vector:

#include <vector>

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {4, 5, 6};

std::vector<int> result;
result.reserve(v1.size() + v2.size());
result.insert(result.end(), v1.begin(), v1.end());
result.insert(result.end(), v2.begin(), v2.end());

Now result contains all elements, while v1 and v2 stay unchanged.

Step by Step Execution

Consider this code:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> a = {10, 20};
    std::vector<int> b = {30, 40};

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

    for (int x : a) {
        std::cout << x << ' ';
    }
}

Step by step:

  1. a starts as [10, 20]
  2. b starts as [30, 40]
  3. a.end() points to the position just after the last element of a
  4. b.begin() points to 30
  5. b.end() points just after 40
  6. insert copies the elements from b into a starting at the end
  7. a becomes [10, 20, 30, 40]
  8. The loop prints all elements of a

Final output:

10 20 30 40

If a does not have enough capacity, it may allocate a larger block of memory before appending the new elements.

Real World Use Cases

Concatenating vectors appears often in real C++ programs.

Common scenarios

  • Merging search results: combine items returned from different queries
  • Batch processing: append one batch of records to another before processing
  • Game development: combine lists of visible objects, enemies, or events
  • Parsing and tokenizing: merge token lists from multiple sources
  • Data pipelines: collect values from several processing stages into one container
  • Testing: combine expected values or test data sets

Example: collecting IDs from two services

std::vector<int> apiIds = {101, 102};
std::vector<int> cachedIds = {90, 95};

std::vector<int> allIds;
allIds.reserve(apiIds.size() + cachedIds.size());
allIds.insert(allIds.end(), cachedIds.begin(), cachedIds.end());
allIds.insert(allIds.end(), apiIds.begin(), apiIds.end());

This pattern is useful when building a final list from multiple sources.

Take Quiz

Real Codebase Usage

In production code, developers usually choose the concatenation style based on ownership, performance, and readability.

Common patterns

Append into an existing vector

items.insert(items.end(), moreItems.begin(), moreItems.end());

Use this when items is the main collection being built.

Reserve before append

items.reserve(items.size() + moreItems.size());
items.insert(items.end(), moreItems.begin(), moreItems.end());

This is common in performance-sensitive code.

Build a new result vector

std::vector<int> combined;
combined.reserve(a.size() + b.size());
combined.insert(combined.end(), a.begin(), a.end());
combined.insert(combined.end(), b.begin(), b.end());

Use this when you want to keep inputs unchanged.

Move instead of copy when possible

For vectors containing expensive-to-copy objects, developers may move elements:

#include <iterator>

v1.insert(v1.end(),
          std::make_move_iterator(v2.begin()),
          std::make_move_iterator(v2.end()));

This can be useful when v2 is no longer needed in its original state.

Related coding patterns

  • Validation before append: check that data is valid before merging
  • Early return: skip work if the source vector is empty
  • Builder pattern: create one output vector gradually from many inputs
  • Error handling: ensure partially built results are still valid if exceptions occur

Common Mistakes

1. Expecting + to work

This does not work for std::vector in standard C++:

std::vector<int> a = {1, 2};
std::vector<int> b = {3, 4};

auto c = a + b; // Error

Fix

Use insert instead.

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

2. Forgetting that insert modifies the target vector

std::vector<int> a = {1, 2};
std::vector<int> b = {3, 4};

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

After this, a changes. If you need both originals unchanged, create a new vector first.

3. Not reserving space when performance matters

This is correct, but may reallocate multiple times for large vectors:

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

Better for large data

result.reserve(a.size() + b.size());
result.insert(result.end(), a.begin(), a.end());
result.insert(result.end(), b.begin(), b.end());

4. Using moved-from elements without understanding the result

v1.insert(v1.end(),
          std::make_move_iterator(v2.begin()),
          std::make_move_iterator(v2.end()));

After moving, the elements in v2 are still present, but their values may be in a moved-from state. Do not assume they still hold the original data.

5. Invalidating iterators and references

If a vector reallocates during insertion, iterators, pointers, and references to its elements may become invalid.

Risky pattern

auto it = a.begin();
a.insert(a.end(), b.begin(), b.end());
// it may now be invalid

Safer approach

Get iterators again after insertion if needed.

Comparisons

ApproachModifies original vector?Efficient?Best use case
v1.insert(v1.end(), v2.begin(), v2.end())YesYesAppend v2 into v1
Create new vector and insert bothNoYesKeep both inputs unchanged
Loop with push_backYes or NoUsually less convenientGood for custom logic per element
Move iterators with insertYesOften very efficientWhen source elements can be moved

insert vs push_back loop

Using insert

v1.insert(v1.end(), v2.begin(), v2.end());
  • shorter
  • clearer intent
  • standard solution for appending a range

Using a loop

for (const auto& x : v2) {
    v1.push_back(x);
}
  • useful if you need to transform or validate elements while appending
  • more verbose for simple concatenation

Copy vs move

MethodWhat happens
Copy insertElements from source are copied into destination
Move insertElements are moved into destination when possible

Use copy when you still need the original values in the source vector. Use move when the source can be safely consumed.

Take Quiz

Cheat Sheet

Quick reference

Append one vector to another

v1.insert(v1.end(), v2.begin(), v2.end());

Append with reserved capacity

v1.reserve(v1.size() + v2.size());
v1.insert(v1.end(), v2.begin(), v2.end());

Create a new concatenated vector

std::vector<int> result;
result.reserve(v1.size() + v2.size());
result.insert(result.end(), v1.begin(), v1.end());
result.insert(result.end(), v2.begin(), v2.end());

Move elements instead of copying

result.insert(result.end(),
              std::make_move_iterator(v.begin()),
              std::make_move_iterator(v.end()));

Rules to remember

  • std::vector has no standard + operator
  • insert is the usual way to concatenate vectors
  • reserve can improve performance
  • insertion may invalidate iterators and references if reallocation happens
  • use move iterators only if the source vector's element values are no longer needed

Edge cases

  • appending an empty vector does nothing
  • concatenating large vectors may allocate significant memory
  • if you need both vectors unchanged, build a separate result vector

FAQ

How do you concatenate two std::vector objects in C++?

Use insert:

v1.insert(v1.end(), v2.begin(), v2.end());

This appends all elements from v2 to v1.

Is there a + operator for std::vector in C++?

No. Standard C++ does not provide operator+ for std::vector.

What is the most efficient way to combine two vectors?

Usually, reserve enough space first and then use insert:

v1.reserve(v1.size() + v2.size());
v1.insert(v1.end(), v2.begin(), v2.end());

Does concatenating vectors copy the elements?

Yes, by default. If appropriate, you can move elements instead of copying them.

Can I concatenate vectors without changing the originals?

Yes. Create a third vector and insert both ranges into it.

What happens if the destination vector runs out of space?

It reallocates to a larger memory block, which may invalidate iterators, pointers, and references.

Should I use a loop with push_back instead of insert?

Use insert for straightforward concatenation. Use a loop if you need custom processing for each element.

Take Quiz

Mini Project

Description

Build a small C++ program that combines two lists of numbers into one result vector. This demonstrates the standard way to concatenate vectors and also shows how to preserve the original vectors when needed.

Goal

Create a program that merges two std::vector<int> objects into a third vector and prints the combined result.

Requirements

Requirement 1 Requirement 2 Requirement 3

Take Quiz

Keep learning

Related questions

View more