将一个向量复制到另一个向量的快速方法


155

我更喜欢两种方式:

void copyVecFast(const vec<int>& original)
{
  vector<int> newVec;
  newVec.reserve(original.size());
  copy(original.begin(),original.end(),back_inserter(newVec));
}

void copyVecFast(vec<int>& original)
{

  vector<int> newVec;
  newVec.swap(original); 
}

你怎么做呢?


14
第二个名称具有误导性-因为它不是副本(虽然很快)。
匿名

Answers:


126

如果通过引用发送参数,则第二个示例不起作用。你的意思是

void copyVecFast(vec<int> original) // no reference
{

  vector<int> new_;
  new_.swap(original); 
}

那会起作用,但是更简单的方法是

vector<int> new_(original);

好,行得通。但这不适用于向量数组:例如:vector <int> A [n];
ABcDexter 2014年

8
那就是交换,而不是复制。
2017年

1
@sdd-不,不是。检查参数列表。original是function参数的副本。
rlbond

249

它们不一样,是吗?一个是副本,另一个是掉期。因此,函数名称。

我最喜欢的是:

a = b;

其中ab是矢量。


3
实际上,方法是按值传递,编译器调用复制构造函数,然后交换该新创建的元素。这就是rlbond建议直接调用复制构造函数以实现相同效果的原因。
大卫·罗德里格斯(DavidRodríguez)-德里贝斯2009年

1
但是,如果没有将原始值作为val传递的函数,则无法调用rlbon。否则,原始的将为空。第二种解决方案确保您将始终按值调用,因此不会丢失原始向量中的日期。(假设掉期与指针交易)
Eyad Ebrahim

那不会将b的元素移动到a(留下b且大小== 0)吗?
乔纳森。

1
@乔纳森 假设您正在谈论的a = b话就不行。分配方式:a平等b而不改变b。相比之下,std::swap(a, b)将交换它们的内容(所以bs size现在将a是以前的任何东西)。您可能正在考虑移动操作(就像在C ++ 11中那样,但是在这样的普通分配中却没有)。这一举措将离开b在,啊哈,“有趣”的状态-看stackoverflow.com/questions/17730689/...
丹尼尔·埃里克

1
@乔纳森 注意双“&”号&&。该版本仅用于右值引用。它不会匹配任何非const值(b例如上面的示例)。您可以b说出一句话,a = std::move(b);请参见en.cppreference.com/w/cpp/language/value_category以获得更高级别的复杂性。
Daniel Earwicker 2014年

74

这是复制向量的另一种有效方法,只需使用其构造函数即可:

std::vector<int> newvector(oldvector);

这比使用std::copy将整个向量从头到尾遍历std::back_insert到新向量中要简单得多。

就是说,您的.swap()一个不是副本,而是交换了两个向量。您将修改原始文件,使其不再包含任何内容!这不是副本。


19

直接回答:

  • 使用=运算符

我们可以使用std::vector::operator=容器的public成员函数std::vector将向量中的值分配给另一个向量。

  • 使用构造函数

此外,构造函数也很有意义。以另一个向量为参数的构造函数(例如xx以相同的顺序构造一个容器,其中每个元素都具有的副本。

警告:

  • 不使用 std::vector::swap

std::vector::swap并没有向量复制到另一个向量,实际上是交换两个向量的元素,正如其名称所示。换句话说,要从中复制的源向量在std::vector::swap调用之后被修改,这可能与您预期的不一样。

  • 深拷贝还是浅拷贝?

如果源向量中的元素是指向其他数据的指针,则有时需要深度复制。

根据维基百科:

深层副本,表示已取消引用字段:不是对要复制的对象进行引用,而是为任何引用的对象创建新的副本对象,并将这些对象的引用放置在B中。

实际上,C ++当前没有内置的方法可以进行深层复制。上面提到的所有方法都是浅浅的。如果需要深拷贝,则可以遍历向量并手动制作参考的拷贝。或者,可以考虑使用迭代器进行遍历。关于迭代器的讨论超出了这个问题。

参考文献

页面std::vector上cplusplus.com


14

您不应使用swap复制向量,否则会更改“原始”向量。

将原始参数作为参数传递给新参数。


14
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2

-14

如果向量已经存在并且您只想复制,则可以执行以下操作:

newVec.resize(oldVec.size());
memcpy(&newVec.at(0), &oldVec.at(0), oldVec.size());

1
请不要记忆。另外,由于memcpy采用字节大小,因此这将不起作用。同样,如果另一个向量已经存在,您可以执行newVec = oldVec与其他答案之一相同的操作。
FDinoff

是的,你是对的。我没看到 @FDinoff,尽管下面的方法可行,但为什么建议不使用memcpy?它似乎比newVec = oldVec快得多。memcpy(&newVec.at(0),&oldVec.at(0),oldVec.size()* sizeof(int));
sgowd

1
在一般情况下,在不调用其副本构造函数的情况下复制对象可能会导致细微的错误。在这种情况下,我会以为他们会有同样的表现。如果没有,我会说向量没有进行性能优化,因为它应该已经这样做了。您是否实际编写了基准?
FDinoff 2015年

我并不是在批评您。.我的团队负责人也提出了同样的建议,我试图理解。
2015年

(我不认为您是在批评我。)还有一些您不理解的东西吗?
FDinoff
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.