右值引用:必须绑定到右值的引用,使用&&来获取右值引用
左值:左值拥有持久的状态
右值:右值拥有短暂的状态(是临时对象)
左值引用和右值引用:
- int i = 10;
- int& b = i;//左值引用,i是一个变量
- int&& c = i + 10;//右值引用, i+10是一个临时的值
注意:不能将右值引用绑定到一个右值引用类型上
- int&& c = i + 10;//右值引用, i+10是一个临时的值
- int&& d = c;//报错:c为左值,不能赋给右值引用
move 可以把左值变为右值
- int&& c = i + 10;//右值引用, i+10是一个临时的值
- int&& d = move(c);//move 把左值转换为右值
移动构造函数的第一个参数是一个右值引用,和拷贝构造函数一样,任何额外的参数必须有默认参数
- class person
- {
- public:
- int* a;
- int* b;
- int* c;
- person(person&& s)noexcept //noexcept 代表不会抛出异常
- //成员初始化器接管s中的资源
- :a(s.a), b(s.b), c(s.c)
- {
- //令s进入这种状态--对其使用析构函数是安全的
- s.a = s.b = s.c = nullptr;
- }
- };
相比于拷贝构造函数,移动构造函数不分配任何新的内存,直接接管给定的person中的内存。
右值引用和成员函数:
在容器中的push_back中,有种构造方式
- void push_back(const type &);/使用拷贝的方法
- void push_back(type&&);//使用的是移动
- 在一个函数定义后面加& 表示要被左值对象调用
- 在一个函数定义后面加&& 表示要被右值对象调用
- class son
- {
- public:
- int a;
- son(int b) :a(b){}
- void show()&
- {
- cout << a << endl;
- }
- void show1()&&
- {
- cout << a << endl;
- }
- };
- int main()
- {
- son p(2);
- p.show();
- p.show1();//报错:要右值对象才能调用
- move(p).show1();//要先转换为右值,才能使用
- return 0;
- }
const 要放在 &的前面
- class son
- {
- public:
- int a;
- son(int b) :a(b){}
- void show()const&
- {
- cout << a << endl;
- }
-
- };