788
votes

How do I concatenate two std::vectors?

26
The answers given don't actually concatenate. They append a copy. There may be a use (for efficiency's point of view) to create a std::vector concatenate method, however it would require some sophisticated sharing of the management of the nodes and that's probably why it hasn't been done. - Douglas Daseeco
@FauChristian: No, there may not be a use from an efficiency's point of view. Vector memory must be continuous, so what you are suggested is impossible. If you wanted "some sophisticated sharing of the management of the nodes", and if you were to change the vector class in such a way, you would end up with a deque. Even then it is very difficult to reuse memory in the way suggested, albeit it would start being a bit more feasible. I don't think it is currently implemented. The main thing is that in such a sharing of management nodes (a deque) the end node might be partially empty. - Cookie
Am I the only one wondering why this is not implemented as a + b or a.concat(b) in the standard library? Maybe the default implementation would be suboptimal, but every array concatenation does not need to be micro-optimized - oseiskar
years of evolution, the most advanced operator-overloading of any mainstream language, a templating system that doubles the complexity of the language, and yet the answer is not v = v1 + v2; - Spike0xff
My guess is the STL didn't want to over-specify the language in case you wanted the operator to do something different, say adding force vectors in a physics model. In that case you might want to overload forceVector1 + forceVector2 to do itemwise addition in clear, concise code. - Jonathan Lidbeck

26 Answers

844
votes
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
238
votes

If 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.

166
votes

I would use the insert function, something like:

vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
79
votes

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.

68
votes

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>.

41
votes
std::vector<int> first;
std::vector<int> second;

first.insert(first.end(), second.begin(), second.end());
29
votes

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());
}
22
votes

With range v3, you may have a lazy concatenation:

ranges::view::concat(v1, v2)

Demo.

18
votes

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());
}
13
votes

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;
12
votes

You should use vector::insert

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

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).

9
votes

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;
}
6
votes

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]

6
votes

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.

4
votes

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.

3
votes
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
3
votes

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
3
votes

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;
}
1
votes

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.

1
votes

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()))

0
votes

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:

  1. Your vector contains primitives
  2. Your contained primitives are of size 32-bit or smaller
  3. You want a const container

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

0
votes

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).

0
votes

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
votes

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.

-5
votes

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());