• 【C++右值引用】左右值的交叉引用的具体情景,右值详讲


    目录

    1.右值和左值

    2.左值引用和右值引用 

    3.移动构造

    4.移动构造和移动赋值的默认生成条件(重载赋值的右值引用和移动构造跟拷贝构造差不多) 

    5.万能引用 (模板参数引用&&)


    1.右值和左值

    左值与右值是C语言中的概念,但C标准并没有给出严格的区分方式,一般认为:可以放在=左边的,或者能 够取地址的称为左值,只能放在=右边的,或者不能取地址的称为右值,但是也不一定完全正确

    左值可以取地址,可以赋值的

    • 下面的a,r1,p,r2就属于左值
    • b,r3虽然是被const修饰不能赋值,但是也是左值,左值是能取地址的值,可以被const修饰也是左值
    1. int a = 10;
    2. int& r1 = a;
    3. int* p = &a;
    4. int& r2 = *p;
    5. const int b = 10;
    6. const int& r3 = b;

    右值:不能取地址的值

    • 纯右值,比如:X+Y, 10。
    • 将亡值,比如:表达式的中间结果((X+(Y+Z))Y+Z的值)、函数按照值的方式进行返回(返回值)。 
    1. //常见的右值
    2. 10;
    3. x + y;
    4. min(x, y);

    2.左值引用和右值引用 

    • 左值引用:b,d
    • 右值引用:a1,b1,c1

    左值引用使用:&,右值引用使用:&&同时它们也是可以交叉引用

    1. //左值引用左值
    2. int a=1;
    3. int& b=a;
    4. int* c=&a;
    5. int& d=*c;
    6. int X=10,int Y=20;
    7. //右值引用右值
    8. int&& a1=10;
    9. int&& b1=X+Y;
    10. int&& c1=min(X,Y);

     2.1左右值的交叉引用

    • 左值引用右值-- 不能直接引用,但是const 左值引用可以引用右值

    • 右值引用左值-- 不能直接引用,但是可以右值引用可以引用move以后左值

    1. //左值引用右值-- 不能直接引用,但是const 左值引用可以引用右值
    2. const int& a=2;
    3. //右值引用左值-- 不能直接引用,但是可以右值引用可以引用move以后左值
    4. int a1=1000000;
    5. int&& b1=move(a1)

    2.2左值引用右值的具体情景

    1. 当参数直接传常数(右值),那么引用必须加一个const

    3.移动构造

    1. class string
    2. {
    3. public:
    4. // 拷贝构造
    5. string(const string& s)
    6. :_str(new char[strlen(s._str) + 1])
    7. , _size(s._size)
    8. , _capacity(s.s_capacity)
    9. {
    10. cout << "string(const string& s) -- 深拷贝" << endl;
    11. strcpy(_str, s._str);
    12. }
    13. // 移动构造
    14. string(string&& s)
    15. :_str(nullptr)
    16. , _size(s._size)
    17. , _capacity(s._capacity)
    18. {
    19. cout << "string(string&& s) -- 资源转移" << endl;
    20. _str = s._str;
    21. s._str = nullptr;
    22. }
    23. string operator+(char ch)
    24. {
    25. string tmp(*this);
    26. push_back(ch);
    27. return tmp;
    28. }
    29. private:
    30. char* _str;
    31. size_t _size;
    32. size_t _capacity; // 不包含最后做标识的\0
    33. };

    3.1移动构造:资源转移,没有了深拷贝和delete效率大大提高

    1. 没有深拷贝了,析构也减少了,效率提升;
    2. 将亡值资源被转移了,它被换成nullptr,调析构函数,没有资源需要析构效率提高 

     3.5push_back的右值引用的重载

    • 所有容器调用push_back都有左值引用和右值引用版本

    4.移动构造和移动赋值的默认生成条件(重载赋值的右值引用和移动构造跟拷贝构造差不多) 

    • 移动构造和移动赋值默认生成条件:当它本身被实现,且析构函数、拷贝构造、赋值运算符重载都没有实现才会默认生成;

    5.万能引用 (模板参数引用&&)

    • 万能引用就是模板参数引用,使用的符号和右值引用相同:&&
    • 可以接受左值也可以接受右值
    • 接受后使用退化成了左值
    1. void Fun(int& x) { cout << "左值" << endl; }
    2. void Fun(int&& x) { cout << "右值" << endl; }
    3. void Fun(const int& x) { cout << "const 左值" << endl; }
    4. void Fun(const int&& x) { cout << "const 右值" << endl; }
    5. template<class T>
    6. void PerfectForward(T&& t)
    7. {
    8. Fun(t);
    9. //Fun(std::forward(t));
    10. }
    11. int main()
    12. {
    13. PerfectForward(10); // 右值
    14. int a;
    15. PerfectForward(a); // 左值
    16. PerfectForward(std::move(a)); // 右值
    17. const int b = 8;
    18. PerfectForward(b); // const 左值
    19. PerfectForward(std::move(b)); // const 右值
    20. return 0;
    21. }

    5.1完美转发 

    完美转发是目标函数总希望将参数按照传递给转发函数(forward)实际类型转给目标函数,而不产生额外的开销;如果相应实参是左值,它就应该被转发为左值;如果相 应实参是右值,它就应该被转发为右值

    格式:forward<模板参数>(实参)

    使用完美转发结果:

  • 相关阅读:
    English语法_介词 - on
    web前端期末大作业——基于Bootstrap响应式汽车经销商4S店官网21页
    3.qt-图解Weiler-Atherton任意多边形剪裁算法
    C++ 语言学习 day06 string , 异常
    机器学习:PCA(Principal Component Analysis主成分)降维
    【Python+selenium】自动化生成测试报告
    基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流
    分析Java 8中 Objects 类源码
    1084 外观数列
    项目:金融行业反欺诈模型
  • 原文地址:https://blog.csdn.net/m0_72964546/article/details/127944769