C++ 通过保留和复制还是通过创建和交换来复制向量更有效?

C++ 通过保留和复制还是通过创建和交换来复制向量更有效?,c++,algorithm,vector,stl,C++,Algorithm,Vector,Stl,我试图有效地复制一个向量。我认为有两种可能的办法: std::vector<int> copyVecFast1(const std::vector<int>& original) { std::vector<int> newVec; newVec.reserve(original.size()); std::copy(original.begin(), original.end(), std::back_inserter(newVec));

我试图有效地复制一个向量。我认为有两种可能的办法:

std::vector<int> copyVecFast1(const std::vector<int>& original)
{
  std::vector<int> newVec;
  newVec.reserve(original.size());
  std::copy(original.begin(), original.end(), std::back_inserter(newVec));
  return newVec;
}

std::vector<int> copyVecFast2(std::vector<int>& original)
{
  std::vector<int> newVec;
  newVec.swap(original);
  return newVec;
}
std::vector copyVecFast1(常量std::vector和原始)
{
std::vector newVec;
newVec.reserve(original.size());
std::copy(original.begin()、original.end()、std::back_inserter(newVec));
返回newVec;
}
std::vector copyVecFast2(std::vector和原件)
{
std::vector newVec;
新矢量交换(原件);
返回newVec;
}

以下哪一项是首选的,为什么?我正在寻找最有效的解决方案,以避免不必要的复制。

但它们不一样,是吗?一个是副本,另一个是交换。因此函数名

我最喜欢的是:

a = b;

其中
a
b
是向量。

不应使用swap复制向量,它会更改“原始”向量


将原始文件作为参数传递给新文件

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

std::vector<int> newvector(oldvector);
std::vector newvector(oldvector);
这比使用
std::copy
将整个向量从头到尾遍历到
std::back\u将它们插入新向量更简单


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

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

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

  vector<int> new_;
  new_.swap(original); 
}
void copyVecFast(vec-original)//无参考
{
新向量;
新互换(原件);
}
这会起作用,但更简单的方法是

vector<int> new_(original);
vector new(原件);
直接回答:
  • 使用
    =
    运算符
我们可以使用容器
std::vector
的公共成员函数
std::vector::operator=
将值从一个向量分配给另一个向量

  • 使用构造函数
此外,构造函数也有意义。具有另一个向量作为参数的构造函数(例如,
x
)使用
x
中每个元素的副本以相同的顺序构造容器

警告:
  • 不要使用
    std::vector::swap
std::vector::swap
不是将一个向量复制到另一个向量,它实际上是交换两个向量的元素,正如其名称所示。换句话说,在调用
std::vector::swap
后,将修改要从中复制的源向量,这可能不是您所期望的

  • 深拷贝还是浅拷贝
如果源向量中的元素是指向其他数据的指针,那么有时需要深度拷贝

根据维基百科:

深度复制,意味着字段被取消引用:不是对被复制对象的引用,而是为任何被引用对象创建新的复制对象,对这些对象的引用放在B中

<>实际上,目前C++中没有一种内置的方式来做深层拷贝。以上提到的所有方法都是肤浅的。如果需要深度复制,可以遍历向量并手动复制引用。或者,可以考虑使用迭代器进行遍历。关于迭代器的讨论超出了这个问题

工具书类

第二个名称有误导性,因为它不是一个副本(尽管它很快)。事实上,该方法是通过值传递,编译器调用复制构造函数,然后交换新创建的元素。这就是为什么rlbond建议直接调用复制构造函数以达到相同的效果。但是,如果没有将原始值作为val传递的函数,则不能调用rlbon。否则,原始值将为空。第二种解决方案确保始终按值调用,因此不会丢失原始向量中的日期。(假设交换处理指针)这不会将b的元素移动到a(使b的大小==0)?@Jonathan。假设你说的是
a=b
,那么“否”。赋值的意思是:使
a
等于
b
,而不改变
b
。相比之下,
std::swap(a,b)
将交换它们的内容(因此
b
大小将是
a
之前的大小)。您可能正在考虑移动操作(在C++11中发生,但在这样的普通赋值中不发生)。这样的举动将使
b
处于一种“有趣”的状态——见@Jonathan。请注意双符号和
&&
。该版本将仅用于右值引用。它不会匹配任何非常量值(如上面示例中的
b
)。您可以通过说
a=std::move(b)将
b
转换为一查看更高级别的复杂性。很好,它可以工作。但它对向量数组不起作用:例如:向量A[n];这是交换,不是复制。@sdd-不,不是。检查参数列表
original
是函数参数的副本。@rlbond意外地否决了答案:(,你能编辑帖子,这样我就可以删除否决票而放弃放弃票吗?对我来说更灵活的是
a=b;
,因为我已经有了成员字段
a
,我只需要用
b
中的新值来分配它
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2