c++引用学习笔记

c++引用学习笔记,第1张

引用变量是一个别名,通过它可以 *** 作其所引用的变量

特点
  1. 引用必须要进行初始化,不能单独存在
  2. 引用一经绑定之后,不能再改变其指向
  3. 引用底层实现就是指针,它是一个受到限制的指针
  4. 引用的使用跟普通的变量是一致的。
指针与引用的区别 指针的特点
  1. 指针是可以单独存在,也不一定要进行初始化
  2. 指针是可以改变指向的,比引用更灵活,但同时风险更高
  3. 指针需要进行间接访问,才能得到相应的数据
引用作为函数的返回值时:
  1. 不能返回局部变量的引用
  2. 不要轻易返回堆空间变量的引用,除非你有了内存回收的策略
把引用作为参数

相当于变量的别名,可以直接修改引用绑定的变量

**引用 约等于 const * **

左值与右值引用 左值与右值

左值

  1. 可以取地址的,有名字的,非临时的就是左值
  2. 非匿名对象,函数返回的引用,const对象等都是左值
  3. 用户创建的,通过作用域规则可知其生存期的,就是左值(包括函数返回的局部变量的引用以及const对象)

右值

  1. 不能取地址的,没有名字的,临时的就是右值 立即数,函数返回的值等都是右值
  2. 从本质上理解右值,创建和销毁由编译器幕后控制,程序员只能确保在本行代码有效的,就是右值(包括立即数)
传统的左值引用

代码实现

int a = 10;
int &b = a;  //定义一个左值引用变量
b = 20;      //通过左值引用修改引用内存的值

左值引用在汇编层面其实和普通的指针是一样的;定义引用变量必须初始化,因为引用其实就是一个别名,需要告诉编译器定义的是谁的引用。

int & var = 10

上述代码无法编译通过,因为10无法进行取地址 *** 作,无法对一个立即数取地址,因为立即数并没有在内存中存储,而是存储在寄存器中,可以通过以下方法进行引用

const int & var = 10;

使用常引用来引用常量数字10,因为此刻内存上产生了临时变量保存了10, 这个临时变量是可以进行取地址 *** 作的,因此var引用的其实是这个临时变量相当于以下 *** 作

代码实现

const int temp = 10;
const int & var = temp;

左值引用要求右边的值必须能够取地址,如果无法取地址,可以用常饮用,但使用常饮用后,我们只能通过引用来读取数据,无法去修改数据,因为其被const修饰成常量引用了。

右值引用

右值往往是没有名称的,因此要使用它只能借助引用的方式。这就产生一个问题,实际开发中我们可能需要对右值进行修改(实现移动语义时就需要),显然左值引用的方式是行不通的。为此,C++11 标准新引入了另一种引用方式,称为右值引用,用 “&&” 表示。

定义右值引用的格式

类型名 && 引用名 = 右值表达式
//例
int && var = 10;

在汇编层面右值引用做的事情与常引用是相同的,即产生临时量来存储常量。唯一的区别在于右值引用可以进行读写 *** 作,而常引用只能进行读 *** 作

右值引用的存在并不是为了取代左值引用,而是利用右值(特别是临时对象)的构造来减少对象构造和析构 *** 作以达到提高效率的目的

右值引用的使用

和声明左值引用一样,右值引用也必须立即进行初始化 *** 作,且只能使用右值进行初始化

 int num = 10;
 //int && a = num; //右值引用不能初始化为左值
 int && a = 10;

右值引用可以修改右值

int && a = 10;
a = 11;
cout << a << endl;

C++语法之定义常量右值引用

const int && a = 10;

这种形式的右值引用并没有实际用处。

一方面,右值引用主要用于移动语义和完美转发,其中前者需要有修改右值的权限

其次,常量右值引用的作用就是引用一个不可修改的右值,这项工作完全可以交给常量左值引用完成

左值引用和右值引用的相互绑定

需要遵循以下规则

  1. 非const左值引用只能绑定到非const左值

  2. const左值引用可绑定到const左值、非const左值、const右值、非const右值

  3. 非const右值引用只能绑定到非const右值,但不适用于函数模板的形参

  4. const右值引用可绑定到const右值和非const右值,它没有显示意义(毕竟右值引用的初衷在于移动语义,而移动语义就意味着修改)

总结

非常量左值引用可以引用的值的类型只有非常量左值,常量左值引用非常量左值、常量左值及右值

测试

int num = 10;
int & a = num;  //编译成功,非常量左值引用支持引用非常量左值
const int num2 = 100;
int & b = num2; //编译失败,非常量左值引用不支持引用常量左值
int & c= 10;    //编译失败,非常量左值引用不支持引用右值

const int & d = num; //编译成功,常量左值引用支持引用非常量左值
const int & e = num2;//编译成功,常量左值引用支持引用常量左值
const int & f = 100; //编译成功,常量左值引用支持引用右值

右值引用不支持引用左值;非常量右值引用可以引用的值的类型只有非常量右值,常量右值引用可以引用非常量右值、常量右值

测试

int num = 10;
const int num2 = 100;
int && a = num;       //编译失败,非常量右值引用不支持引用非常量左值
int && b = num2;      //编译失败,非常量右值引用不支持引用常量左值
int && c = 10;        //编译成功,非常量右值引用支持引用非常量右值
const int && d = num; //编译失败,常量右值引用不支持引用非常量左值
const int && e = num2;//编译失败,常量右值引用不支持引用常量左值
const int && f = 100; //编译成功,常量右值引用支持引用右值

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1325510.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-12
下一篇2022-06-12

发表评论

登录后才能评论

评论列表(0条)

    保存