在向量中移动一系列元素与复制相比有什么好处?

问题描述

请考虑以下代码段(在大型仿真代码中看到了与此类似的代码

std::vector<int> v1{1,2,3,4,5,6,7};
std::vector<int> v2;

std::move(v1.begin() + 2,v1.end(),back_inserter(v2));

在这里,我将一系列元素从v1移到v2,但是与复制相比,这样做有什么特别的优势吗?我实际上看不出move在这里的优势是什么,因为它在int范围内运行。实际上,由于我们正在处理POD类型,因此我不相信有任何进展。

如果我们想将整个v1转移到v2,那么我们可以这样做:

v2 = std::move(v1);

此处的强制转换将使v2现在拥有指向v1先前拥有的连续内存范围的指针,从而避免了复制。

但是在一系列要素的前一步中,我看不到有用性。

解决方法

在这里,我正在将一系列元素从v1移到v2,但是有没有 与复制相比有什么特别的优势?

。这只是发生范围应付,因为您对原始类型使用std::move确实可以应付。因此,如果您要进行以下操作,它与简单操作一样:

std::vector<int> v2{v1.begin() + 2,v1.end()};

因此,您对发现是正确的。但是,它称为fundamental types/ primitive types,而不是POD。


但是在先前一系列元素的移动中,我看不到有用性。

考虑std::vector</*expensive copy type*/>的情况,在这种情况下,只要有可能,都应移动基础范围元素。

例如考虑std::vector<std::string>情况

std::vector<std::string> v1{ "1","2","3","4","5","6","7" };
std::vector<std::string> v2;
// reserve memory for unwanted reallocations
v2.reserve(std::distance(v1.begin() + 2,v1.end()));

// moves the string element in the range
std::move(v1.begin() + 2,v1.end(),back_inserter(v2));

// v1 now: 1 2
// v2 now: 3 4 5 6 7 

See a demo here


请注意,对于迭代器,也可以使用std::make_move_iterator来在声明时(如果有意思的话)进行范围移动构造,而不是在单独的行中使用std::move来代替范围。 / p>

#include <iterator> // std::make_move_iterator

std::vector<std::string> v1{ "1","7" };
std::vector<std::string> v2{ std::make_move_iterator(v1.begin() + 2),std::make_move_iterator(v1.end()) };