To add on top of François Andrieux's answer, std::vector has a ranged insert() member function. Just passing in the iterators to your vector of unique_ptr won't work, but there's a way to convert the dereferencing of those iterators from lvalues to xvalues: std::move_iterator and its corresponding factory function: std::make_move_iterator:
sharedV.insert(sharedV.end(),
std::make_move_iterator(uniqueV.begin()),
std::make_move_iterator(uniqueV.end()));
The reason this may be more efficient than using std::back_inserter is that insert() will know up front what the resulting size will be, so only at most one allocation needs to be done and then none of the actual insertions need to do size checks.
This is so awkward to write that I would suggest range-based overloads of this named extend():
template <class T, class Range>
void extend(std::vector<T>& dst, Range&& range) {
using std::begin; using std::end;
if constexpr (std::is_lvalue_reference<Range>{}) {
dst.insert(dst.end(), begin(range), end(range));
} else {
dst.insert(dst.end(),
std::move_iterator(begin(range)), std::move_iterator(end(range)));
}
}
That's C++17, but is easily doable in C++14. Just takes more typing. You would then write:
extend(sharedV, std::move(uniqueV));