01 对象的移动(资源的转移)
为了支持移动操作,新标准引入了右值引用(右值:临时对象)
所谓的右值引用,就是必须绑定到右值的引用(需要窃取右值对象的资源,能够操作右值)
我们通过&&来获取右值引用(给右值取一个别名),最大的特点就是只能绑定到一个将要销毁的对象
因此,我们可以将一个右值引用绑定的对象的资源 “移动” 到另一个对象中
移动操作背后的思想就是将左值的处理和右值的处理分离:拷贝操作(拷贝构造/拷贝赋值) 接收 左值
Student s1;
Student s2 = s1; // 左值 -----> 拷贝构造
// s1是左值,只是在此次当做右值使用
// 左值即可以当做左值使用,也可以当做右值使用
// 右值只能当做右值使用
=================================
Student s1;
Student s2;
s2 = s1; // 左值 -----> 拷贝赋值(赋值运算符重载)
// s1是左值,只是在此次当做右值使用
移动操作也分为:移动构造和移动赋值移动操作(移动构造/移动赋值) 接收 右值
Student s1 = Student{"zhangsan", 25}; // 用来初始化的是右值,调用移动构造函数
=================================
Student s1;
s1 = Student{"zhangsan", 25}; // 用来赋值的是右值,调用移动赋值函数(也是一种赋值运算符重载)
移动构造和移动赋值接收非const 的右值引用参数,除了完成资源的移动,移动操作还必须确保移动后销毁“原对象”是安全的,而且,一旦资源移动完成,原对象必须不再拥有被移动了的资源
由于移动操作“窃取”资源,通常不分配资源,因此通常不会抛出异常,对于不抛出异常的函数,在新标准中应该使用 noexcept 加以声明
默认情况下(任何构造函数都不写的情况下),编译器会为一个类生成以下函数:
一个默认的构造函数 X()
一个拷贝构造函数 X(const X &)
一个拷贝赋值函数 X & operator=(const X &)
一个移动构造函数 X(X &&)
一个移动赋值函数 X & operator=(X &&)
一个析构函数 ~X()
如果写了移动函数,编译器就不会生成默认的拷贝操作
写了拷贝操作,编译器就不会生成默认的移动操作