How do I concatenate two std::vectors?
30 Answers
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
12 Comments
vector1.capacity() >= 2 * vector1.size(). Which is atypical unless you've called std::vector::reserve(). Otherwise the vector will reallocate, invalidating the iterators passed as parameters 2 and 3..concat or += or somethingIf you are using C++11, and wish to move the elements rather than merely copying them, you can use std::move_iterator along with insert (or copy):
#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;
}
This will not be more efficient for the example with ints, since moving them is no more efficient than copying them, but for a data structure with optimized moves, it can avoid copying unnecessary state:
#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;
}
After the move, src's element is left in an undefined but safe-to-destruct state, and its former elements were transfered directly to dest's new element at the end.
6 Comments
std::move(src.begin(), src.end(), back_inserter(dest))?insert might allocate necessary amount of memory in one turn. When back_inserter might lead to several reallocationsstd::make_move_iterator() ?I would use the insert function, something like:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
Comments
Or you could use:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
This pattern is useful if the two vectors don't contain exactly the same type of thing, because you can use something instead of std::back_inserter to convert from one type to the other.
7 Comments
reserve first. The reason std::copy is sometimes useful is if you want to use something other than back_inserter.if > capacity_ in push_back if a problem. It's a problem enough that the memset in resize does not matter.With C++11, I'd prefer following to append vector b to a:
std::move(b.begin(), b.end(), std::back_inserter(a));
when a and b are not overlapped, and b is not going to be used anymore.
This is std::move from <algorithm>, not the usual std::move from <utility>.
9 Comments
insert way which is safer.insert() with move_iterators? If so, how?std::move we are talking here, since most people don't know this overload. Hope it's an improvement.7 Comments
std::vector::append_range(). An non-mutating concat would still be nice.I prefer one that is already mentioned:
a.insert(a.end(), b.begin(), b.end());
But if you use C++11, there is one more generic way:
a.insert(std::end(a), std::begin(b), std::end(b));
Also, not part of a question, but it is advisable to use reserve before appending for better performance. And if you are concatenating vector with itself, without reserving it fails, so you always should reserve.
So basically what you need:
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());
}
6 Comments
std:: if the type of a comes from std, which defeats the generic aspect.In C++23, it is possible to concatenate a range to a standard container using its member function append_range, if present.
Thus, the concatenation of two std::vector objects can be performed in following way:
vec1.append_range(vec2);
2 Comments
A general performance boost for concatenate is to check the size of the vectors. And merge/insert the smaller one with the larger one.
//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());
}
5 Comments
v1.insert(v2.end()... is using an iterator into v2 to specify the position in v1.There is an algorithm std::merge from C++17, which is very easy to use when the input vectors are sorted,
Below is the example:
#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;
}
2 Comments
std::vector::insert, but it does to something different: merging two ranges into a new range vs inserting one vector at the end of another. Worth mentioning in the answer?If you want to be able to concatenate vectors concisely, you could overload the += operator.
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;
}
Then you can call it like this:
vector1 += vector2;
2 Comments
+= might be perceived as a modification element-wise.std. This means either the symbols have to be defined/pulled into the global namespace to be discovered, or in the same namespace as any code using it. Not really ideal over just a named function that doesn't have any of these issues.Using C++20 you can get rid of begin() and end() with ranges.
#include <ranges>
std::ranges::copy(vec2, std::back_inserter(vec1));
or if you want to move elements:
std::ranges::move(vec2, std::back_inserter(vec1));
1 Comment
vec2 to vec1, not the other way around.You should use vector::insert
v1.insert(v1.end(), v2.begin(), v2.end());
1 Comment
If you are interested in strong exception guarantee (when copy constructor can throw an exception):
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;
}
}
Similar append_move with strong guarantee can't be implemented in general if vector element's move constructor can throw (which is unlikely but still).
2 Comments
v1.erase(... to throw too?insert already handles this. Also, this call to erase is equivalent to a resize.If your goal is simply to iterate over the range of values for read-only purposes, an alternative is to wrap both vectors around a proxy (O(1)) instead of copying them (O(n)), so they are promptly seen as a single, contiguous one.
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
Refer to https://stackoverflow.com/a/55838758/2379625 for more details, including the 'VecProxy' implementation as well as pros & cons.
Comments
Add this one to your header file:
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;
}
and use it this way:
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 will contain [1,2,62]
4 Comments
using namespace std; or using std::vector; in the header file... or worse, it's putting this function template in the std namespace.Here's a general purpose solution using C++11 move semantics:
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);
}
Note how this differs from appending to a vector.
1 Comment
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
1 Comment
You can prepare your own template for + operator:
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;
}
Next thing - just use +:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
This example gives output:
1 2 3 4 5 6 7 8
1 Comment
T operator+(const T & a, const T & b) is dangerous, it is better to use vector<T> operator+(const vector<T> & a, const vector<T> & b).I've implemented this function which concatenates any number of containers, moving from rvalue-references and copying otherwise
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;
}
Comments
For containers which offer push_back (string, vector, deque, ...):
std::copy(std::begin(input), std::end(input), std::back_inserter(output))
and
for containers which offer insert (maps, sets):
std::copy(std::begin(input), std::end(input), std::inserter(output, output.end()))
1 Comment
push_back it's more efficient to call v1.insert(v1.end(), v2.begin(), v2.end()) than to invoke pushing in a loop (which std::copy does)Before C++23:
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
Since C++23:
vec1.append_range(vec2);
In addition, if you only want to iterate over the concatenated result, there's views::concat or ranges::concat_view, also available in range-v3:
std::vector vec1{1, 2, 3}, vec2{4, 5};
for (auto x : std::views::concat(vec1, vec2))
std::println("{}", x);
Comments
This solution might be a bit complicated, but boost-range has also some other nice things to offer.
#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;
}
Often ones intention is to combine vector a and b just iterate over it doing some operation. In this case, there is the ridiculous simple join function.
#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;
}
For large vectors this might be an advantage, as there is no copying. It can be also used for copying an generalizes easily to more than one container.
For some reason there is nothing like boost::join(a,b,c), which could be reasonable.
Comments
If what you're looking for is a way to append a vector to another after creation, vector::insert is your best bet, as has been answered several times, for example:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
Sadly there's no way to construct a const vector<int>, as above you must construct and then insert.
If what you're actually looking for is a container to hold the concatenation of these two vector<int>s, there may be something better available to you, if:
- Your
vectorcontains primitives - Your contained primitives are of size 32-bit or smaller
- You want a
constcontainer
If the above are all true, I'd suggest using the basic_string who's char_type matches the size of the primitive contained in your vector. You should include a static_assert in your code to validate these sizes stay consistent:
static_assert(sizeof(char32_t) == sizeof(int));
With this holding true you can just do:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
For more information on the differences between string and vector you can look here: https://stackoverflow.com/a/35558008/2642059
For a live example of this code you can look here: http://ideone.com/7Iww3I
Comments
You can do it with pre-implemented STL algorithms using a template for a polymorphic type use.
#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;
}
You can clear the second vector if you don't want to use it further (clear() method).
Comments
I tried to solve this task in C++17 without using the rangesV3 library. After reading some posts in this topic, I made this solution:
namespace algorithms
{
/*!
* \brief Wraps incoming element and move/or copy the elements from one to another.
* \example return (wrapped_plus(container) + ...).value
*/
template <class T>
struct wrapped_plus {
using value_type = T;
value_type value;
wrapped_plus(value_type&& in) : value(std::move(in)) {}
wrapped_plus(const value_type& in) : value(in) {}
wrapped_plus operator+(const wrapped_plus& in)
{
std::copy(std::begin(in.value), std::end(in.value), std::back_inserter(value));
return *this;
}
wrapped_plus operator+(wrapped_plus&& in)
{
std::move(std::make_move_iterator(std::begin(in.value)), std::make_move_iterator(std::end(in.value)), std::back_inserter(value));
return *this;
}
};
/*!
* \brief Merge 2 or more STL containers with same type.
* \example merge(container,container,container)
*/
template <typename... Containers>
static inline auto merge(Containers&&... c)
{
return (wrapped_plus(c) + ...).value;
}
} // namespace algorithms
int main(int argc, char** argv)
{
std::vector<int> dest{1,2,3,4,5};
std::vector<int> src{6,7,8,9,10};
auto result = algorithms::merge(dest,src);
return 0;
}
Comments
Concatenate two std::vector-s with for loop in one 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];
}
3 Comments
auto iterators instead of manual indexing. You don't care about what index you are concatenating only that it is done sequentially.To be honest, you could fast concatenate two vectors by copy elements from two vectors into the other one or just only append one of two vectors!. It depends on your aim.
Method 1: Assign new vector with its size is the sum of two original vectors' size.
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
Method 2: Append vector A by adding/inserting elements of vector 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());
5 Comments
std::move_iterator so that elements are moved instead of copied. (see en.cppreference.com/w/cpp/iterator/move_iterator).setcapacity? What is function: ?resize method.Try, create two vectors and add second vector to first vector, code:
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.
Description:
While i int not v2 size, push back element , index i in v1 vector.
a + bora.concat(b)in the standard library? Maybe the default implementation would be suboptimal, but every array concatenation does not need to be micro-optimizedforceVector1 + forceVector2to do itemwise addition in clear, concise code.