c++中移动语义std:move()定义:
template <class T>
typename remove_reference<T>::type&& move (T&& arg) noexcept {
return static_cast<remove_reference<decltype(arg)>::type&&>(arg);
}- 作用:将左值转为右值引用。
- 使用场景:将不再继续使用的左值继续用在其它方面,以节省内存开销和对象拷贝开销。
- 原理理解:
Many components of the standard library implement move semantics, allowing to transfer ownership of the assets and properties of an object directly without having to copy them when the argument is an rvalue.
翻译:许多标准库组件实现了移动语义,当对象是一个右值时,在不拷贝对象的情况下转移这个对象的资源和属性的拥有权。
理解:
(1) 这个对象必须是一个右值;
(2) 不用拷贝对象;
(3) 是转移的对象资源的拥有权,如图1。
Although note that -in the standard library- moving implies that the moved-from object is left in a valid but unspecified state. Which means that, after such an operation, the value of the moved-from object should only be destroyed or assigned a new value; accessing it otherwise yields an unspecified value.
翻译:尽管如此,在标准库里,移动语义说明被移动的对象处于有效但未指定的状态。也就是说,在std::move()执行后,被移动的对象的值应当被销毁或者赋予一个新值;访问这个被移动的对象会出现一个不确定的值。
理解:
(1) 对象经过std::move()执行后,处于有效但未指定的状态。
"有效但未指定"的理解:
如:Student stu2 = std::move(stu1); stu1是一个有效的声明,但是stu1里的值是不确定的。
4.实现原理。
如下代码,实现原理是:
(1)类中声明移动构造函数;
(2)std::move()将左值转为右值再调用时,就会调用移动构造函数;
(3)移动构造函数实现了两个功能点:a.数据初始化,2.销毁被移动对象数据。
class Info {
public:
Info():age(0){}
Info(int age):age(age){}
int age;
};
class Student {
public:
Student() : info(nullptr) {}
Student(const Student& stu) { //拷贝构造函数
cout << "constructor" << endl;
}
Student(Student&& stu) noexcept : info(stu.info) { //移动构造函数
stu.info = nullptr;
cout << "Move constructor" << endl;
}
~Student() {};
Info* info;
};
int main(){
Student stu;
stu.info = new Info(20);
Student stu1(stu); //调用拷贝构造函数
cout << stu.info->age << endl;
Student stu2(std::move(stu)); //调用移动构造函数
cout << stu2.info->age << endl;
return 0;
}
输出:
constructor
20
Move constructor
205.误用
(1)任何场景都用std::move(),但是其实是需要类中实现了移动语义功能才行(移动构造函数+数据初始化+销毁被移动对象数据)
int a = 100;
int b = std::move(a); //这样是不对的,这样依然进行了拷贝。6.思考
需要透彻理解std::move(),还是需要根据其定义、原理,且结合实践代码理解,不实践写代码去实现移动语义是很难透彻理解的。