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