行业知识
【C++练级之路】【Lv.22】C++11——右值引用和移动语义
2026-11-03 18:49:43
来源:互联网转载
快乐的流畅:个人主页 个人专栏:《算法神殿》《数据结构世界》《进击的C++》 远方有一堆篝火,在为久候之人燃烧!
文章目录
- 引言
- 一、右值引用
- 1.1 左值和右值
- 1.2 左值引用和右值引用的范围
- 1.3 左值引用的意义
- 二、移动语义
- 2.1 移动构造
- 2.2 移动赋值
- 2.3 右值引用的意义
- 2.4 move
- 2.5 移动插入
- 三、完美转发
- 3.1 万能引用
- 3.2 forward
- 四、新增默认成员函数
- 4.1 移动构造函数
- 4.2 移动赋值重载
- 4.3 default
- 4.4 delete
引言
关于C++11的final和override的知识,在之前已经提到过,这里不再赘述,有需要的请移步这篇博客【C++练级之路】【Lv.13】多态(你真的了解虚函数和虚函数表吗?)
一、右值引用
1.1 左值和右值
- 左值:可取地址,可在等号左右
- 右值:不可取地址,只能在等号右边
void test(){int a;//左值10;//右值10 + 20;//右值}一般情况下,左值均为变量名,而右值则为字面常量、表达式等。
1.2 左值引用和右值引用的范围
void test(){int& ref1 = a;//左值引用,可以引用左值//int& ref2 = a + b;//左值引用,不能引用右值(权限放大)const int& ref2 = a + b;//const左值引用,可以引用右值int&& ref3 = a + b;//右值引用,可以引用右值//int&& ref4 = a;//右值引用,不能引用左值int&& ref4 = move(a);//右值引用,可以引用move后的左值}- 左值引用,可以引用左值
- const左值引用,可以引用右值
- 右值引用,可以引用右值
- 右值引用,可以引用move后的左值
ps:move的作用,是将左值强制转换为右值引用,详情见move章节。
ps:右值的引用属性为左值,将右值引用后,右值会被存储起来,并可以取到地址。
1.3 左值引用的意义
左值引用:
- 传引用传参,减少拷贝
- 传引用返回,减少拷贝(限制:函数内的局部对象,不能传引用返回)
左值引用已经解决了绝大多数拷贝问题,但是唯一的缺陷就是不能传引用返回局部对象。所以,这就是右值引用存在的意义,为了补全这块不足。
而要完全理解右值引用的意义,则需要学习移动语义,理解右值引用是如何减少拷贝的。
二、移动语义
首先,给出一个自己实现的精简版string类,方便调试和观察内部细节。
namespace my{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""): _size(strlen(str)), _capacity(_size){//cout std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}// 拷贝构造string(const string& s):_str(nullptr){cout cout delete[] _str;_str = nullptr;}void reserve(size_t n){if (n _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size = _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '';}string& operator+=(char ch){push_back(ch);return *this;}string operator+(char ch){string tmp = *this;tmp += ch;return tmp;}private:char* _str;size_t _size;size_t _capacity; // 不包含最后做标识的};}string tmp = *this;tmp += ch;return tmp;}my::string s1 = "hello";my::string s2 = s1 + '!';}cout my::string s1 = "hello";my::string s2;s2 = s1 + '!';}cout // forward _Arg as movablereturn ((typename remove_referencestring s1 = "hello";string s2 = move(s1);}vector} cout cout cout cout Fun(t);}void test(){PerfectForward(10);//右值int a;PerfectForward(a);//左值PerfectForward(move(a));//右值const int b = 8;PerfectForward(b);//const 左值PerfectForward(move(b));//const 右值}Fun(forwardpublic:Person(const char* name = "", int age = 0):_name(name), _age(age){}//Person(const Person& p)//:_name(p._name)//,_age(p._age)//{}//Person& operator=(const Person& p)//{//if(this != &p)//{//_name = p._name;//_age = p._age;//}//return *this;//}//~Person()//{}private:my::string _name;int _age;};Person s1;Person s2 = s1;Person s3 = move(s1);//移动构造Person s4;s4 = move(s2);//移动赋值}
上一篇:【MySQL】数据库中常用的函数
下一篇:服务器坏了怎么调亮度快?