• C++11—关于引用Reference


    1. 引用的声明(Reference declaration)

    引用分为左值引用和右值引用(什么是左值和右值?参考文章:【译】理解C和C++中的左值和右值)。引用是为一个已存在的对象或函数取的别名。如:

    1. int func()
    2. {
    3. return 4;
    4. }
    5. int main(int argc, char* argv[])
    6. {
    7. int a = 10;
    8. // lvalue reference initialize
    9. int& lr_a = a;
    10. // rvalue reference initialize
    11. int&& rr_a = 1 + 2;
    12. int&& rr_f = func();
    13. return 0;
    14. }

    注意:

    1. 声明引用时必须进行初始化。
    2. 没有对void类型对象的引用,也没有对引用类型的引用。
    3. 没有引用类型的数组,也没有引用类型的指针。下面的代码会报错:
    1. int main(int argc, char* argv[])
    2. {
    3. int a = 10;
    4. int& arr[3] = {a, a, a};
    5. int& *p = &lr_a;
    6. return 0;
    7. }
    8. PS F:\Jungle\1.Program\4.C++\5.C++11\02.reference> g++ -o app .\main.cpp
    9. .\main.cpp: In function 'int main(int, char**)':
    10. .\main.cpp:30:15: error: declaration of 'arr' as array of references
    11. int& arr[3] = {a, a, a};
    12. ^
    13. .\main.cpp:31:11: error: cannot declare pointer to 'int&'
    14. int& *p = &lr_a;

    2. 引用折叠(Reference collapsing)

    引用折叠(或者引用坍塌), 是指当引用指向引用的时候,此处的引用可以是左值也可以是右值引用,最终的类型会有部分被折叠到一起。

    • 当右值引用指向右值引用时,最终的类型为右值引用
    • 其他情况(如右值引用指向左值引用,左值引用指向左值引用,左值引用指向右值引用),最终的类型为左值引用
    1. typedef int& lref;
    2. typedef int &&rref;
    3. int n;
    4. lref &r1 = n; // type of r1 is int&
    5. lref &&r2 = n; // type of r2 is int&
    6. rref &r3 = n; // type of r3 is int&
    7. rref &&r4 = 1; // type of r4 is int&&

    3. 左值引用

    一个左值,代表一个在内存中占有确定位置的对象,简言之,左值在内存中有地址。左值引用可以作为一个已存在的对象的别名来使用。

    1. int main(int argc, char* argv[])
    2. {
    3. int a = 10;
    4. int& b = a;
    5. std::cout << " a address : " << &a << std::endl;
    6. std::cout << " b address : " << &b << std::endl;
    7. std::cout << " a = " << a << "\t b = " << b << std::endl;
    8. std::cout << "change a to 11: ";
    9. a = 11;
    10. std::cout << " a = " << a << "\t b = " << b << std::endl;
    11. b = 12;
    12. std::cout << "change b to 12: ";
    13. std::cout << " a = " << a << "\t b = " << b << std::endl;
    14. const int& c = a;
    15. // c = 13; error : cannot change a through reference to const
    16. return 0;
    17. }

    运行上述代码:

    1. a address : 0x22fe44
    2. b address : 0x22fe44
    3. a = 10 b = 10
    4. change a to 11: a = 11 b = 11
    5. change b to 12: a = 12 b = 12

    可以看到,左值引用和原对象a的地址是一样的。改变b实际上会改变a,反之亦然。

    4. 右值引用

    右值是什么呢?我们这么来定义:非左即右。一个对象不是左值就是右值,如果能够通过左值的定义判断一个对象是左值,那么它就是左值;否则就是右值。通过上述左值的定义也可以看出,右值在内存中没有确定位置的地址。

    C++11推出了右值引用。右值引用可以延长一些临时对象的生命周期。右值引用的特点是:它将让其所绑定的右值重获新生,即使该右值本身是一个临时变量,但是它本身却不能绑定任何左值。

    1. int a = 10;
    2. // int &&r0 = a; error : 不能将右值引用绑定到左值
    3. int&& r1 = 1 + 2; // ok, 右值引用绑定到一个临时对象

    右值引用常用于移动语义(移动构造、移动赋值和完美转发),以节省深拷贝引起的开销。

  • 相关阅读:
    Jenkins学习笔记
    2021年电工杯数学建模A题高铁牵引供电系统运行数据分析及等值建模求解全过程论文及程序
    2022,一个Java程序猿的装机配置
    opentelemetry、grafana、Prometheus、jaeger、victoria-metrics 介绍、关系与使用
    精通Nginx(05)-http工作机制、指令和内置变量
    MySQL 45 讲 | 13 为什么表数据删掉一半,表文件大小不变?
    浅谈USB的枚举过程
    Qt写一个文档复制粘贴助手app
    Java基础单元测试
    quarkus数据库篇之四:本地缓存
  • 原文地址:https://blog.csdn.net/sinat_21107433/article/details/126320433