如何连接两个<code>std::vector ?


#1楼

我会使用insert函数 ,类似:

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

#2楼

vector1.insert( vector1.end(), vector2.begin(), vector2.end() );

#3楼

std::vector<int> first;
std::vector<int> second;first.insert(first.end(), second.begin(), second.end());

#4楼

或者您可以使用:

std::copy(source.begin(), source.end(), std::back_inserter(destination));

如果两个向量不包含完全相同的事物类型,则此模式很有用,因为您可以使用某些东西代替std :: back_inserter来将一种类型转换为另一种类型。


#5楼

如果您使用的是C ++ 11,并且希望移动元素而不是仅复制它们,则可以将std::move_iterator与insert(或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;
}

对于具有int的示例,这将不会更加高效,因为移动它们并不比复制它们更有效,但是对于具有优化移动的数据结构,它可以避免复制不必要的状态:

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

移动之后,src的元素处于未定义但可以安全销毁的状态,并且其先前的元素最后直接转移到dest的新元素。


#6楼

如果您对强大的异常保证感兴趣(当复制构造函数可以引发异常时):

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

如果向量元素的move构造函数可以抛出(不太可能,但仍然可以),则通常无法实现具有强烈保证的类似append_move


#7楼

对于C ++ 11,我更喜欢以下将向量b附加到a:

std::move(b.begin(), b.end(), std::back_inserter(a));

ab不重叠时,并且b将不再使用。


这是std::move<algorithm> ,不是通常 std::move<utility>


#8楼

将此添加到您的头文件:

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

并以这种方式使用它:

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将包含[1,2,62]


#9楼

如果您要查找的是在创建后将向量附加到另一个向量的方法,那么vector::insert是您最好的选择,例如多次回答,例如:

vector<int> first = {13};
const vector<int> second = {42};first.insert(first.end(), second.cbegin(), second.cend());

遗憾的是,无法构造const vector<int> ,如上所述,您必须先构造然后insert


如果您实际上正在寻找的是容纳这两个vector<int>的串联的容器,那么在以下情况下,可能会有更好的选择:

  1. 您的vector包含基元
  2. 您所包含的原语大小为32位或更小
  3. 你想要一个const容器

如果上述全部正确,则建议使用char_typevector包含的基元大小匹配的basic_string 。 您应该在代码中包含static_assert ,以验证这些大小保持一致:

static_assert(sizeof(char32_t) == sizeof(int));

有了这个信念,您就可以做到:

const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

有关stringvector之间差异的更多信息,请参见此处: https : //stackoverflow.com/a/35558008/2642059

有关此代码的实时示例,请参见此处: http : //ideone.com/7Iww3I


#10楼

我更喜欢已经提到的一种:

a.insert(a.end(), b.begin(), b.end());

但是,如果您使用C ++ 11,则还有另一种通用方法:

a.insert(std::end(a), std::begin(b), std::end(b));

同样,这也不是问题的一部分,但是建议在追加之前使用reserve以提高性能。 而且,如果您将vector与自身连接在一起,而没有保留它将会失败,那么您始终应该reserve


所以基本上您需要什么:

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

#11楼

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

#12楼

老实说,您可以通过将两个向量中的元素复制到另一个向量中来快速连接两个向量,或者仅追加两个向量之一! 这取决于您的目标。

方法1:分配新向量,其大小是两个原始向量大小的总和。

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

方法2:通过添加/插入向量B的元素来附加向量A。

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

#13楼

对于范围v3 ,您可能会有一个懒惰的串联:

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

演示


#14楼

您应该使用vector :: insert

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

#15楼

这是使用C ++ 11 move语义的通用解决方案:

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

请注意,这与appendvector有何不同。


#16楼

连接的一般性能提升是检查向量的大小。 并合并/插入较小的一个与较大的一个。

//vector<int> v1,v2;
if(v1.size()>v2.size()){v1.insert(v1.end(),v2.begin(),v2.end());
}else{v1.insert(v2.end(),v1.begin(),v1.end());
}

#17楼

您可以为+运算符准备自己的模板:

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

接下来-使用+:

vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)cout << x << " ";
cout << endl;

此示例提供输出:

 

1 2 3 4 5 6 7 8


#18楼

这个解决方案可能有点复杂,但是boost-range还提供了其他一些不错的东西。

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

通常,人们的意图是将向量ab组合在一起,然后对其进行迭代以执行某些操作。 在这种情况下,存在可笑的简单join功能。

#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 iteratorfor (auto& iter : boost::join(a, boost::join(b, c))) {std::cout << iter << " ";}std::cout << "\n";// Can also be used to create a copystd::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;
}

对于大向量,这可能是一个优势,因为没有复制。 它也可以用于将概图轻松复制到多个容器中。

由于某些原因,没有什么可能是boost::join(a,b,c)


#19楼

如果希望能够简洁地连接向量,则可以重载+=运算符。

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

然后您可以这样称呼它:

vector1 += vector2;

#20楼

我已经实现了此功能,该功能可以连接任意数量的容器,从右值引用移至其他位置进行复制

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

#21楼

C ++ 17有一个算法std::merge ,非常易于使用,

下面是示例:

#include <iostream>
#include <vector>
#include <algorithm>int main()
{//DATAstd::vector<int> v1{2,4,6,8};std::vector<int> v2{12,14,16,18};//MERGEstd::vector<int> dst;std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));//PRINTfor(auto item:dst)std::cout<<item<<" ";return 0;
}

#22楼

如果您的目标只是为了只读而遍历整个值范围,则另一种方法是将两个向量都包装在代理(O(1))周围,而不是复制它们(O(n)),因此它们在外部视为单个连续的。

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 30std::cout << AB[6]; // ----> 20

有关更多详细信息,请参见https://stackoverflow.com/a/55838758/2379625 ,包括“ VecProxy”实施以及优缺点。

连接两个std :: vector相关推荐

  1. 连接两个点云中的字段或数据形成新点云以及Opennni Grabber初识

    (1)学习如何连接两个不同点云为一个点云,进行操作前要确保两个数据集中字段的类型相同和维度相等,同时了解如何连接两个不同点云的字段(例如颜色 法线)这种操作的强制约束条件是两个数据集中点的数目必须一样 ...

  2. C++入门经典-例6.14-通过指针连接两个字符数组

    1:字符数组是一个一维数组,引用字符数组的指针为字符指针,字符指针就是指向字符型内存空间的指针变量. char *p; char *string="www.mingri.book" ...

  3. std::set, std::list, std::vector在erase的区别

    erase函数接口原型 1. std::list::erase // c++98: iterator erase (iterator position); iterator erase (iterat ...

  4. PCL——连接两个点云的字段

    连接两个点云的字段 1. 示例代码 2. 上面出现的PointT类型 2.1 PointXYZ 2.2 Normal 2.3 PointNormal 1. 示例代码 以下代码参照PCL官方文档:htt ...

  5. std::vector介绍

    文章来源:http://blog.csdn.net/willoj/article/details/2252543 vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算 ...

  6. c++的*号是否有空格的区别以及char*转std::vector<float>解析

    文章目录 一.前言 二.正文 1.*带不带空格的区别 2.char*和char** 3.关于指针运算 4.char指针转std::vector<float> 解析 (1)const cha ...

  7. 逐步释放质疑怎么样释放std::vector所占用的内存空间

    我只听见硬盘 嘎吱嘎吱地响,Window 98已累患上对键盘.鼠标一无反映 总的说来,C/C++的内存办理照旧太庞大了,步伐员忙这些个工作就够了,没法搞出Java同样更"高级"的庞 ...

  8. C++ std::vector删除元素的几种方式及区别

    容器vector在删除过程中,常用的函数. 函数 作用 pop_back() 删除 vector 容器中最后一个元素,该容器的大小(size)会减 1,但容量(capacity)不会发生改变. era ...

  9. c++ std vector用法介绍

    c++ vector 一部分内容来自:http://blog.csdn.net/phoebin/article/details/3864590:http://www.cnblogs.com/wang7 ...

最新文章

  1. 入职体检体检错了_我们如何更新入职体验并获得更多用户
  2. matlab-等高线图-三维曲线的绘制
  3. winform/timer控件/权限设置/三级联动
  4. 小马儿随笔——实地参观A级数据中心
  5. VTK:几何对象之LinearCell
  6. 阿里云 docker php mysql_PHP开发环境02 - 阿里云Ubuntu使用Docker配置PHP环境(只限于学习)...
  7. 别再谈Python2与Python3区别, 反正我一个按钮随意转换代码!
  8. 02-方法-课后思考
  9. 托微软的福,谷歌把GitLab捧成了独角兽
  10. matlab转自张朋飞
  11. 《oracle每天一练》Oracle冷备份与数据恢复
  12. 中国气候变暖绝对是事实
  13. 基于java的康泰小区物业管理系统的设计与实现毕业设计源码101926
  14. Dorado7 首页菜单CSS调整
  15. adsl拨号服务器构建代理池
  16. mie散射理论方程_A. Mie米散射理论基础知识讲解
  17. 如何解决下载链接在微信中无法打开的问题
  18. 人工智能个性化和逼真的漫画素描生成输入人脸图像创建漫画照片
  19. prototype是原型对象,那__proto__又是什么呢,总不能是别名吧?
  20. 整理10种电脑截图工具(附带下载地址)

热门文章

  1. zabbix使用JMX监控tomcat性能
  2. Java Web的分页工具类
  3. 小数据作为解题关键:
  4. Linux编程学习--开篇
  5. input type=file图片上传时,先预览
  6. 如何才能成为一个高效工作的软件工程师?
  7. Linux 的文件软链接如何删除
  8. Oracle--plsql之控制结构
  9. Linux字符设备驱动
  10. Windows平台下MySQL常用操作与命令