move() 算法会将它的前两个输入迭代器参数指定的序列移到第三个参数定义的目的序列的开始位置,第三个参数必须是输出迭代器。这个算法返回的迭代器指向最后一个被移动到目的序列的元素的下一个位置。
这是一个移动操作,因此无法保证在进行这个操作之后,输入序列仍然保持不变;源元素仍然会存在,但它们的值可能不再相同了,因此在移动之后,就不应该再使用它们。如果源序列可以被替换或破坏,就可以选择使用 move() 算法。如果不想扰乱源序列,可以使用 copy() 算法。
本文作者原创,转载请附上文章出处与本文链接。
C++ move()排序函数用法详解(深入了解,一文学会)目录
1 左值和右值
要了解move函数首先弄清左值引用和右值引用。左值、左值引用、右值、右值引用
左值: 是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体;
右值:当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存器。
注:一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。
2 引用
引用是C++语法做的优化,引用的本质还是靠指针来实现的。引用相当于变量的别名。
引用可以改变指针的指向,还可以改变指针所指向的值。
引用的基本规则:
注:声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象;即引用必须初始化,不能对引用重定义;
对引用的一切操作,就相当于对原对象的操作。
3. 左值引用和右值引用
3.1 左值引用
左值引用的基本语法:type &引用名 = 左值表达式;
3.2 右值引用
右值引用的基本语法type &&引用名 = 右值表达式;
右值引用在企业开发人员在代码优化方面会经常用到。
右值引用的“&&”中间不可以有空格。
std::move并不能移动任何东西,它唯一的功能是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义。从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue);
C++ 标准库使用比如vector::push_back 等这类函数时,会对参数的对象进行复制,连数据也会复制.这就会造成对象内存的额外创建, 本来原意是想把参数push_back进去就行了,通过std::move,可以避免不必要的拷贝操作。
std::move是为性能而生。
std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。
用法:
#include <iostream> // For standard streams
#include <iterator> // For stream iterators and begin() and end()
#include <algorithm> // For reverse_copy() and copy_if()
#include <cctype> // For toupper() and isalpha()
#include <string>
#include <vector>
#include <deque>
using namespace std;
using std::string;
int main()
{
std::vector<std::string> v;
std::string str = "Knock";
std::cout << "Copying str\n";
v.push_back(str); // 使用左值引用版本,将str复制到数组array中
std::cout << "str: " << str << '\n';
std::cout << "vector: " << v[0] << '\n';
std::cout << "\nMoving str\n";
v.push_back(std::move(str)); // 使用右值引用版本,将str移动到数组array中
std::cout << "str: " << str << '\n';
std::cout << "vector:" << v[0] << ' ' << v[1] << '\n';
}
上述例子可以清晰地看出来,复制的时候str中的值没有改变,而在移动的例子中str中的值就已经消失,也就是说真正的把值移动了出去。
4 move_backward()函数
从末尾开始将[first,last]范围内的元素移到终止于结果的范围内。
该函数首先将*(last-1)移至*(result-1),然后向后跟随这些元素之前的元素,直到到达第一个元素(并包括它)。
#include <iostream> // std::cout
#include <algorithm> // std::move_backward
#include <vector>
using namespace std;
int main()
{
std::vector <int> vec1{ 1, 2, 3, 4, 5 };
std::vector <int> vec2{ 7, 7, 7, 7, 7 };
// Print elements
std::cout << "Vector1 contains:";
for (int i = 0; i < vec1.size(); i++)
std::cout << " " << vec1[i];
std::cout << "\n";
// Print elements
std::cout << "Vector2 contains:";
for (unsigned int i = 0; i < vec2.size(); i++)
std::cout << " " << vec2[i];
std::cout << "\n\n";
// std::move_backward function
std::move_backward(vec2.begin(), vec2.begin() + 4, vec1.begin() + 4);
// Print elements
std::cout << "Vector1 contains after std::move_backward function:";
for (unsigned int i = 0; i < vec1.size(); i++)
std::cout << " " << vec1[i];
std::cout << "\n";
return 0;
}