969

How do I concatenate two std::vectors?

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • 10
    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 Feb 15 '17 at 19:07
  • 16
    @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 May 16 '17 at 10:00
  • 17
    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 Mar 24 '18 at 08:40
  • 53
    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 Oct 21 '19 at 16:08
  • 7
    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 Feb 06 '20 at 20:51
  • 3
    @Spike0xff, v = v1 + v2 has a meaning in math that's not concatenating. It has some requirements too in order to be computable. I would rather suggest an append method (shortcut of what can be done using ```insert```) or a push back overload. – Stefano Buora Feb 17 '21 at 14:47
  • https://cplusplus.com/reference/vector/vector/insert/ the referense on `insert()` might be helpful – KNU Apr 27 '23 at 10:00

29 Answers29

1014
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
Robert Gamble
  • 106,424
  • 25
  • 145
  • 137
  • 63
    I'd only add code to first get the number of elements each vector holds, and set vector1 to be the one holding the greatest. Should you do otherwise you're doing a lot of unnecessary copying. – Joe Pineda Oct 14 '08 at 16:11
  • 45
    I have a question. Will this work if vector1 and vector2 are the same vectors? – Alexander Rafferty Jul 17 '11 at 09:36
  • 9
    If you have concatenating several vectors to one, is it helpful to call `reserve` on the destination vector first? – Faheem Mitha Feb 04 '12 at 23:07
  • 41
    @AlexanderRafferty: Only if `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. – Drew Dormann Jun 21 '12 at 20:30
  • 8
    @FaheemMitha: Since arguments of `insert` are vectors, it's already know how many elements are ahead and will handle it itself. If we were inserting other things like array, it was useful to reserve the space first. – Aidin Apr 14 '14 at 01:35
  • 1
    @Khaur: That's horrifying to the point it's hard to believe. It's super trivial for an implementation to detect the iterators are random access, calculate the size, and pre-reserve the needed space. I think MSFT's even does that for forward iterators. – Mooing Duck Apr 05 '16 at 16:23
  • @MooingDuck You're right, I missed the dispatcher and thought the input iterator version applied for all types of iterators. The forward iterator version does a lot more stuff. Thanks for pointing it out, I deleted my initial comment so that it doesn't show up without yours. – Khaur Apr 14 '16 at 16:14
  • 56
    It's too bad there isn't a more succinct expression in the standard library. `.concat` or `+=` or something – nmr Oct 14 '16 at 23:32
  • 14
    @nmr In C++, this is _quite_ succinct. – YSC Nov 08 '18 at 13:37
  • 2
    It's hard to get an overview of all the different answers to this question. The `std::vector::insert` approach has been posted in several other answers as well, but this one has most upvotes, so I'll ask/state here: Using `insert` should have an advantage over other approaches which use `back_inserter` because `insert` could potentially memcpy in one bulk while the approaches that use `back_inserter` must iterate over the vector to be inserted element by element. Do I see this right? – j00hi Aug 22 '19 at 15:34
303

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.

Dev Null
  • 4,731
  • 1
  • 30
  • 46
Alex
  • 3,233
  • 1
  • 11
  • 8
  • 14
    The std::make_move_iterator() method helped me when trying to concatenate std::vectors of std::unique_ptr. – Knitschi Dec 27 '14 at 13:43
  • 4
    What's the difference between this and `std::move(src.begin(), src.end(), back_inserter(dest))`? – kshenoy Feb 25 '20 at 07:30
  • 4
    @kshenoy, `insert` might allocate necessary amount of memory in one turn. When `back_inserter` might lead to several reallocations – yrHeTateJlb Oct 01 '20 at 12:23
  • 1
    what's the difference between this and not having `std::make_move_iterator()` ? – road_to_quantdom Jul 12 '22 at 17:42
  • 3
    @road_to_quantdom This will use the move-constructor to move elements from src to dest. Without std::make_move_iterator it will use the copy-constructor. – Carlo Wood Jul 17 '22 at 09:27
188

I would use the insert function, something like:

vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
Jon Cage
  • 36,366
  • 38
  • 137
  • 215
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
92

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.

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
  • 16
    the copy method is a not such a good way. It will call push_back multiple time which means that if a lot of elements have to be inserted this could mean multiple reallocations. it is better to use insert as the vector implementation could do some optimization to avoid reallocations. it could reserve memory before starting copying – Yogesh Arora Mar 22 '10 at 13:16
  • 11
    @Yogesh: granted, but there's nothing stopping you calling `reserve` first. The reason `std::copy` is sometimes useful is if you want to use something other than `back_inserter`. – Roger Lipscombe Mar 22 '10 at 18:36
  • When you say "multiple allocations", that is true - but the number of allocations is at worst log(number of entries added) - which means that the cost of adding an entry is constant in the number of entries added. (Basically, don't worry about it unless profiling shows you need a reserve). – Martin Bonner supports Monica Nov 20 '15 at 13:55
  • You might want to use std::transform to do this instead. –  Feb 07 '16 at 16:01
  • 2
    copy sucks a lot, even with reserve. vector::insert will avoid all the checks: http://quick-bench.com/bLJO4OfkAzMcWia7Pa80ynwmAIA – Denis Yaroshevskiy Jul 29 '18 at 16:31
  • @DenisYaroshevskiy That's a striking difference in performance. Any idea why is that happening? Conceptually, the `using_resize` method writes the memory space of `res` twice, should be the slower one ?? – Samuel Li Nov 12 '20 at 04:47
  • 2
    @SamuelLi - mostly the `if > capacity_` in push_back if a problem. It's a problem enough that the `memset` in `resize` does not matter. – Denis Yaroshevskiy Nov 13 '20 at 07:14
85

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

sam hocevar
  • 11,853
  • 5
  • 49
  • 68
Deqing
  • 14,098
  • 15
  • 84
  • 131
  • 16
    Undefined behaviour if a actually is b (which is OK if you know that can never happen - but worth being aware of in general purpose code). – Martin Bonner supports Monica Nov 20 '15 at 13:53
  • 1
    @MartinBonner Thanks for mentioning that. Probably I should turn back to the old `insert` way which is safer. – Deqing Feb 01 '16 at 03:31
  • just add following header line the begin: #include – Manohar Reddy Poreddy Sep 10 '16 at 12:07
  • 29
    Ah, the OTHER std::move. Quite confusing the first time you see it. – xaxxon Sep 16 '16 at 02:52
  • 4
    Is this different from `insert()` with `move_iterator`s? If so, how? – GPhilo Nov 05 '18 at 10:52
  • 2
    I've added a note about what `std::move` we are talking here, since most people don't know this overload. Hope it's an improvement. – YSC Nov 08 '18 at 13:43
  • @Deqing I'm not sure insert is better... If a is b then as soon as you insert a few elements it will reallocate and invalidate the iterators passed to insert which will then continue to be used, right? – Jerry Jeremiah Sep 21 '20 at 21:26
  • @JerryJeremiah If a is b, then you cannot use `insert` (it would be undefined behavior). Otherwise, `insert` is preferable, because it can compute the number of elements to insert once in advance. – j6t Jan 10 '23 at 09:19
45
std::vector<int> first;
std::vector<int> second;

first.insert(first.end(), second.begin(), second.end());
James Curran
  • 101,701
  • 37
  • 181
  • 258
37

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());
}
ST3
  • 8,826
  • 3
  • 68
  • 92
  • 2
    `std::` is deduced through [argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl). `end(a)` will be enough. – asu Oct 13 '16 at 20:02
  • 5
    @Asu ADL will only add `std::` if the type of `a` comes from `std`, which defeats the generic aspect. – Potatoswatter Dec 27 '16 at 06:59
  • good point. in this case it's a vector so it would work anyways, but yes that's a better solution. – asu Dec 27 '16 at 11:09
  • std::begin()/end() were added for collections (like arrays) which don't have them as member functions. But arrays also don't have an insert() member function, and calls the question "Is there a collection with an insert() but without begin() (which works with the std::begin()) ?" – James Curran Oct 04 '18 at 15:53
  • 2
    you should prefer not to use reserve, as it might come with a massive overhead. Look here: https://stackoverflow.com/a/64102335/7110367 – Ido Kessler Sep 28 '20 at 13:43
  • Be warned that using `insert` to concatenate a vector to itself is outside the specification of `insert` (undefined behavior). Calling `reserve` in advance does not change that. – j6t Jan 10 '23 at 09:30
32

With range v3, you may have a lazy concatenation:

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

Demo.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
22

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());
}
qwr
  • 9,525
  • 5
  • 58
  • 102
Vikramjit Roy
  • 474
  • 5
  • 8
  • So simple, yet I never thought about it that way! – Zimano Mar 15 '19 at 19:41
  • 2
    The sample code is incorrect. `v1.insert(v2.end()...` is using an iterator into `v2` to specify the position in `v1`. – David Stone Jul 05 '19 at 22:16
  • 1
    You can also use a quick swap. @DavidStone I edited it so that the concat order may be changed. Is it possible to add to the beginning of a vector? – qwr Dec 09 '19 at 05:45
  • 1
    You can insert into the beginning, but that will be slower. To truly "concatenate", however, the order typically does matter, so that is what you need to do. – David Stone Dec 10 '19 at 02:12
  • 2
    I don't like this answer because you don't insert v2 after v1 in all case (without specifying it with a note). Otherwise, your answer could be more complete if you add a solution which save the concatenation in another vector rather than modifiying one of them. –  Sep 30 '20 at 20:24
14

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;
}
Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34
  • 14
    I don't think it's any easier to use than `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? – j b Dec 05 '19 at 09:14
  • Ok. I understood what is expected in the answer. I will add. – Pavan Chandaka Oct 26 '20 at 19:03
13

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;
Daniel Giger
  • 2,023
  • 21
  • 20
  • this can be very confusing and is not recommended. `+=` might be perceived as a modification *element-wise*. – Sergey Kolesnik Apr 03 '22 at 11:43
  • This isn't a good idea because the operator won't be found by ADL, since both arguments are from namespace `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. – Human-Compiler Jun 29 '22 at 22:16
10

You should use vector::insert

v1.insert(v1.end(), v2.begin(), v2.end());
Boris
  • 358
  • 2
  • 6
9

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

AlexT
  • 1,413
  • 11
  • 11
8

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.

Ronald Souza
  • 627
  • 1
  • 8
  • 14
8

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));
Olppah
  • 790
  • 1
  • 10
  • 21
6

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]

Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
5

In C++23, it is possible to concatenate a range to a standard container using its member function append_range, if present.

Then, the concatenation of two std::vector can be done as follows:

vec1.append_range(vec2);
LoS
  • 448
  • 1
  • 3
  • 15
  • +1 (though I wish I could give +100). This is by far the best possible answer when physical concatenation must take place. I have an answer of my own in this thread but it applies to cases where physical concatenation is not really needed in practice. It's a shame it took so long for C++ to incorporate sth like this. Finally in Rome :) Thx. – Ronald Souza Jun 28 '23 at 23:25
  • @Ronald Souza, thanks, I am really glad you appreciate my answer :) – LoS Jun 29 '23 at 11:31
4

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.

Daniel
  • 8,179
  • 6
  • 31
  • 56
4

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
Vladimir U.
  • 132
  • 8
  • 5
    Using`T operator+(const T & a, const T & b)` is dangerous, it is better to use `vector operator+(const vector & a, const vector & b)`. – Matthieu H Dec 13 '19 at 15:46
3
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
instance
  • 1,366
  • 15
  • 23
  • 6
    While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please [include an explanation for your code](//meta.stackexchange.com/q/114762/269535), as that really helps to improve the quality of your post. **Flaggers / reviewers:** [For code-only answers such as this one, downvote, don't delete!](//meta.stackoverflow.com/a/260413/2747593) (Note: This answer may actually be simple enough to make an explanation, and thus downvotes, unnecessary. You may still want to add an explanation to prevent more NAA/VLQ flags.) – Scott Weldon Dec 17 '16 at 00:38
3

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;
}
Drew
  • 12,578
  • 11
  • 58
  • 98
3

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

Aroonalok
  • 631
  • 1
  • 7
  • 18
  • For containers with `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) – Xeverous Oct 20 '22 at 22:34
1

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.

Aleph0
  • 5,816
  • 4
  • 29
  • 80
0

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

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
0

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

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
rekkalmd
  • 171
  • 1
  • 12
0

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

COMPLETE EXAMPLE

iikorni
  • 507
  • 5
  • 16
-2

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];
    }
Robert Christopher
  • 4,940
  • 1
  • 20
  • 21
GobeRadJem32
  • 102
  • 3
  • 14
  • 1
    besides it not working, this code is heavily non-idiomatic. You should at least be using `auto` iterators instead of manual indexing. You don't care about what index you are concatenating only that it is done sequentially. – Tarick Welling Jun 08 '20 at 14:06
  • @TarickWelling I don't see why you said this code is not working, could you be more specific ? –  Sep 30 '20 at 20:33
  • 7
    Did you check the date of my comment? You fixed the bugs in your code now it is just not idiomatic. – Tarick Welling Oct 01 '20 at 07:39
-5

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());
Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
nvnhcmus
  • 1
  • 3
-6

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.

GobeRadJem32
  • 102
  • 3
  • 14
  • 1
    Your description is not clear (and useless, sorry). Otherwise, your answer could be more complete if you add a second solution which save the concatenation in another vector rather than modifiying one of them. –  Sep 30 '20 at 20:37