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.
v1is your first row of boxes.v2is a second row of boxes.- Concatenation means taking every box from
v2and placing copies of them at the end ofv1.
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.
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 tov2.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:
astarts as[10, 20]bstarts as[30, 40]a.end()points to the position just after the last element ofab.begin()points to30b.end()points just after40insertcopies the elements frombintoastarting at the endabecomes[10, 20, 30, 40]- 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.
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
| Approach | Modifies original vector? | Efficient? | Best use case |
|---|---|---|---|
v1.insert(v1.end(), v2.begin(), v2.end()) | Yes | Yes | Append v2 into v1 |
Create new vector and insert both | No | Yes | Keep both inputs unchanged |
Loop with push_back | Yes or No | Usually less convenient | Good for custom logic per element |
Move iterators with insert | Yes | Often very efficient | When 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
| Method | What happens |
|---|---|
| Copy insert | Elements from source are copied into destination |
| Move insert | Elements 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.
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::vectorhas no standard+operatorinsertis the usual way to concatenate vectorsreservecan 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.
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
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.