Concatenating two std::vectors

2018-12-31 23:14发布

How do I concatenate two std::vectors?

18条回答
弹指情弦暗扣
2楼-- · 2019-01-01 00:06

If you are using C++11, and wish to move the elements rather than merely copying them, you can use std::move_iterator (http://en.cppreference.com/w/cpp/iterator/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.

查看更多
不流泪的眼
3楼-- · 2019-01-01 00:06

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

查看更多
ら面具成の殇う
4楼-- · 2019-01-01 00:06

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
查看更多
伤终究还是伤i
5楼-- · 2019-01-01 00:07

I would use the insert function, something like:

vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
查看更多
谁念西风独自凉
6楼-- · 2019-01-01 00:08

You should use vector::insert

v1.insert(v1.end(), v2.begin(), v2.end());
查看更多
伤终究还是伤i
7楼-- · 2019-01-01 00:09

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]

查看更多
登录 后发表回答