目录
4.移动构造和移动赋值的默认生成条件(重载赋值的右值引用和移动构造跟拷贝构造差不多)
左值与右值是C语言中的概念,但C标准并没有给出严格的区分方式,一般认为:可以放在=左边的,或者能 够取地址的称为左值,只能放在=右边的,或者不能取地址的称为右值,但是也不一定完全正确。
左值:可以取地址,可以赋值的
- int a = 10;
- int& r1 = a;
- int* p = &a;
- int& r2 = *p;
-
- const int b = 10;
- const int& r3 = b;
右值:不能取地址的值
- //常见的右值
- 10;
- x + y;
- min(x, y);
左值引用使用:&,右值引用使用:&&;同时它们也是可以交叉引用
//左值引用左值 int a=1; int& b=a; int* c=&a; int& d=*c; int X=10,int Y=20; //右值引用右值 int&& a1=10; int&& b1=X+Y; int&& c1=min(X,Y);
2.1左右值的交叉引用
左值引用右值-- 不能直接引用,但是const 左值引用可以引用右值
右值引用左值-- 不能直接引用,但是可以右值引用可以引用move以后左值
- //左值引用右值-- 不能直接引用,但是const 左值引用可以引用右值
- const int& a=2;
-
- //右值引用左值-- 不能直接引用,但是可以右值引用可以引用move以后左值
- int a1=1000000;
- int&& b1=move(a1)
2.2左值引用右值的具体情景
- class string
- {
- public:
- // 拷贝构造
- string(const string& s)
- :_str(new char[strlen(s._str) + 1])
- , _size(s._size)
- , _capacity(s.s_capacity)
- {
- cout << "string(const string& s) -- 深拷贝" << endl;
- strcpy(_str, s._str);
- }
-
- // 移动构造
- string(string&& s)
- :_str(nullptr)
- , _size(s._size)
- , _capacity(s._capacity)
- {
- cout << "string(string&& s) -- 资源转移" << endl;
- _str = s._str;
- s._str = nullptr;
- }
-
- string operator+(char ch)
- {
- string tmp(*this);
- push_back(ch);
-
- return tmp;
- }
-
- private:
- char* _str;
- size_t _size;
- size_t _capacity; // 不包含最后做标识的\0
- };
3.1移动构造:资源转移,没有了深拷贝和delete效率大大提高
3.5push_back的右值引用的重载
- void Fun(int& x) { cout << "左值" << endl; }
- void Fun(int&& x) { cout << "右值" << endl; }
- void Fun(const int& x) { cout << "const 左值" << endl; }
- void Fun(const int&& x) { cout << "const 右值" << endl; }
-
- template<class T>
- void PerfectForward(T&& t)
- {
- Fun(t);
-
- //Fun(std::forward
(t)); - }
- int main()
- {
- PerfectForward(10); // 右值
-
- int a;
- PerfectForward(a); // 左值
- PerfectForward(std::move(a)); // 右值
-
- const int b = 8;
- PerfectForward(b); // const 左值
- PerfectForward(std::move(b)); // const 右值
-
- return 0;
- }
5.1完美转发
完美转发是目标函数总希望将参数按照传递给转发函数(forward)的实际类型转给目标函数,而不产生额外的开销;如果相应实参是左值,它就应该被转发为左值;如果相 应实参是右值,它就应该被转发为右值
格式:forward<模板参数>(实参)
使用完美转发结果: