复制std::vector:更喜欢使用赋值还是std::copy?

96

我有两个向量:

std::vector<int> v1, v2;

// Filling v1
...

现在我需要将v1复制到v2。有没有理由更喜欢使用

v2 = v1;

而不是

std::copy(v1.begin(),v1.end(),v2.begin());

(或者反过来)?


7
赋值运算符会做正确的事情。按照你写的方式进行“复制”,如果 v1 大于 v2,它将出现问题。 - jrok
5
如果在复制后 v1 不再需要,你可以使用 v2.swap(v1); - hmjd
1
写下你想要做的事情。如果你想将一个向量赋值给另一个向量,就写下这个操作。 - Alex Chamberlain
6个回答

123
一般来说,我强烈建议使用v2 = v1:
  1. 它更短,并且使意图更清晰。
  2. std::copy如果v2的长度与v1不同,则无法工作(它不会调整大小,因此在最好的情况下仍将保留一些旧元素(v2.size() > v1.size()),并在程序中覆盖某些随机数据,最坏的情况是)。
  3. 如果v1即将过期(并且您使用C++11),则可以轻松修改v1move内容。
  4. 从性能上讲,赋值操作不太可能比std::copy慢,因为实现者可能会在内部使用std::copy,如果它带来了性能优势。
总之,std::copy表达能力较差,可能会做错事情,而且甚至没有更快。因此,在这里没有任何理由使用它。

16
那么,std::copy 是用来做什么的? - altroware
41
这段话的意思是:它用于将一段范围内的内容复制到另一个范围中。例如,您不能使用赋值运算符从std::list复制到std::vector,也不能从std::vector的一部分复制到该向量的另一部分。 - Benjamin Lindley
3
如果v1在堆栈上分配并被销毁,会发生什么?v2 = v1会导致v1的元素被复制吗? - James Wierzba
元素类型的哪种复制机制被调用?在 vector<int> 的情况下,整数是通过 operator= 还是 int 的复制构造函数从一个向量复制到另一个向量的? - Gauthier
在这种情况下,你会如何实现operator=? - jorge saraiva
2
@james operator=会进行完整的深度复制。惯用的C++使用值语义,因此复制向量会复制其所有元素。唯一的例外是如果它的元素是指针,那么指针会被复制。赋值后,这些向量是独立的。 - Ben

20
如果v2不够大,你使用copy就会导致缓冲区溢出。
你可以使用后插入迭代器,它会调用v2的push_back方法。但是这可能会导致多次重分配,具体取决于v1有多大。
copy(v1.begin(), v1.end(), back_inserter(v2));

最好让vector正确地管理事情。赋值运算符可以做到这一点,同样vector::assign也可以:

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

我有一种直觉,即赋值运算符是用vector::assign实现的。


伍德先生,您是不是想说 v2.assign(v1.begin(), v1.end()) 而不是 v2.assign(v1.begin(), v2.end())? - Peter Schaeffer

13

std::copy的调用可能尝试访问目标向量末尾之外的项目。

使用赋值。

你不必微观优化:这是库作者的责任,最终是编译器的责任。

如果代码不需要正确性,那么可以使其速度任意快。

然而,在copy的情况下,很难确定它是否更快,而且对于一般情况肯定是不正确的。


3
我同意您关于优化的说法,但值得指出的是,编译器或库可用的信息越多,它们执行工作的能力就越好。std::vector 的成员函数知道它们正在处理一个 std::vector,并且了解它是如何实现的,而 std::copy 没有这些信息。结论是,成员函数可能做得更好(肯定不会更差)。 - James Kanze

2

这更短。

std::copy 主要用于复制容器的部分内容。如果你需要复制整个容器,最好使用复制构造函数。


如果 v2 不够大,你将会遭遇缓冲区溢出。 - Peter Wood

2

就目前而言,成员函数更适合。更一般地说,每当向量的大小可能会改变或者完全更改向量的全部内容时,您应该优先考虑使用成员函数。仅在您只替换矢量内的一个小范围时,std::copy 才是适当的选择。


1

赋值操作更加清晰,内部使用std::copy(或unitizalized_copy _M_allocate_and_copy,具体取决于大小和容量),因此性能相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接