当前位置:  开发笔记 > 编程语言 > 正文

连接两个std :: vector

如何解决《连接两个std::vector》经验,为你挑选了9个好方法。

我如何连接两个std::vector



1> Robert Gambl..:
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );


我只添加代码以首先获取每个向量所包含的元素数,并将vector1设置为保持最大的元素.如果你不这样做,你会做很多不必要的复制.
我有个问题.如果vector1和vector2是相同的向量,这会工作吗?
@AlexanderRafferty:仅当`vector1.capacity()> = 2*vector1.size()`时.除非你调用`std :: vector :: reserve()`,否则这是非典型的.否则向量将重新分配,使作为参数2和3传递的迭代器无效.
太糟糕了,标准库中没有更简洁的表达方式.`.concat`或`+ =`等等
如果你将几个向量连接到一个,那么首先在目标向量上调用`reserve`是否有帮助?
@FaheemMitha:由于`insert`的参数是向量,它已经知道前面有多少个元素并且将自己处理它.如果我们插入其他类似数组的东西,那么首先保留空间是有用的.
@nmr在C++中,这是_quite_ succinct.

2> 小智..:

如果您正在使用C++ 11,并希望移动元素而不是仅复制它们,则可以std::move_iterator与insert(或copy)一起使用:

#include 
#include 
#include 

int main(int argc, char** argv) {
  std::vector dest{1,2,3,4,5};
  std::vector 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(std::cout, "\n")
    );

  return 0;
}

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

#include 
#include 
#include 

int main(int argc, char** argv) {
  std::vector> dest{{1,2,3,4,5}, {3,4}};
  std::vector> 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的新元素.


The std::make_move_iterator() method helped me when trying to concatenate std::vectors of std::unique_ptr.

3> Tom Ritter..:

我会使用insert函数,如:

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



4> Roger Lipsco..:

或者您可以使用:

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

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


复制方法不是一个好方法.它将多次调用push_back,这意味着如果必须插入许多元素,这可能意味着多次重新分配.最好使用insert作为向量实现可以做一些优化以避免重新分配.它可以在开始复制之前保留内存
@Yogesh:被授予,但没有什么能阻止你先调用`reserve`.`std :: copy`有时候有用的原因是你想要使用`back_inserter`以外的东西.

5> Deqing..:

使用C++ 11,我更喜欢将vector附加到a:

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

何时ab不重叠,b不再使用.


这是std::move来自,而不是通常 std::move.


啊,OTHER std :: move.第一次看到它时相当混乱.
如果实际上是b,那么未定义的行为(如果您知道这种情况永远不会发生,那就没关系 - 但值得在通用代码中注意).

6> James Curran..:
std::vector first;
std::vector second;

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



7> ST3..:

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

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

但是如果你使用C++ 11,还有一种更通用的方法:

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

此外,不是问题的一部分,但建议reserve在追加更好的性能之前使用.如果你将向量与自身连接起来,没有保留它就会失败,所以你总是应该这样做reserve.


基本上你需要的是:

template 
void Append(std::vector& a, const std::vector& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}


`std ::`是通过[参数依赖查找]推导出来的(http://en.cppreference.com/w/cpp/language/adl).`end(a)`就足够了.
@Asu ADL只会添加`std ::`,如果`a`的类型来自`std`,这会破坏通用方面.

8> 小智..:

你应该使用vector :: insert

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



9> Jarod42..:

使用范围v3,您可能会有一个懒惰的连接:

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

演示.

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有