【C++】引用

最近在看408,可能会捡起来每日一题,emmm反正就每天很充实就是说,要期末八股文太多了hhh

引用

1. 概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它 引用的变量共用同一块内存空间。

  • 引用必须初始化
int a = 1;
int& b = a;
  • 一个变量可以有多个引用
int a = 1;
int& b = a;
int& c = a;
  • 一旦引用了就不能更换了
int a = 1;
int b = 2;
int& c = a;
//c = b;//不可

使用建议:如果引用的地方,不需要改成引用其他地方,可以使用引用


2. 性质

int a = 1;
int& b = a;
a = 10;
//此时b也会变成10
b = 20;
//此时a也会变成20

int a = 1;
int& b = a;
int& c = b;
//可行
  • 引用在不同的作用域可以同名
int a = 10;
int& b = a;
int c = 20;
b = c;//这里是赋值操作,不是b引用c

3. 引用作参数

以防用指针很麻烦

void swap(int& x, int& y)
{
    int tmp = x;
    y = x;
    x = tmp;
}

4. 引用构成重载

虽然引用的底层是指针,但还是跟指针构成重载

void swap(int x, int y)
{
    int tmp = x;
    y = x;
    x = tmp;
}

void swap(int* a, int* b)
{ 
    int tmp = *x;
    *y = *x;
    *x = tmp;
}

void swap(int& x, int& y)
{
    int tmp = x;
    y = x;
    x = tmp;
}

以上三个构成函数重载,在定义的时候不会报错,但在运行的时候(使用的时候)

//取地址能判断
swap(&a, &b);
//而传值的话int 和 int& 不能判断、
//匹配出问题,编译器看不懂
swap(a, b);

5. 引用作返回值

先看普通的int类型返回值如何传参

int add(int a, int b)
{
    int c = a + b;
    return c;
}

在反汇编中

在这里插入图片描述

在销毁函数函数之前,把c的值给寄存器eax

在这里插入图片描述

最后寄存器再传值


引用作为返回值

int& add(int a, int b)
{
	int c = a + b;
	return c;
}

在这里插入图片描述

lea指令用于把源操作数的地址偏移量传送目的操作数

这里是先把c的地址放到rax寄存器,rax再给eax寄存器,再给外面所赋值的地方

在这里插入图片描述

指针试了一下和上面的方式类似,再次说明引用的本质其实是指针


但存在风险:

  • 如果该函数后面再次被调用或者调用其他函数,函数栈帧覆盖了上一次的结果
  • 那么所赋值的c不会是我们需要的原来的值,只会是新的函数栈帧销毁之前该地址的值

6. 传值、传引用作为返回值类型或者参数的性能比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

如果给一个全局变量(在静态区)或者返回的地址是mallc出来的(在堆)或者是返回外部main函数中变量的地址(比如数组)

函数无论怎么调用都不会影响,而传值是拷贝,引用不会被影响且只用拷贝地址

所以引用更快(原因参考第五点)


7. 常引用

//权限相同,b可改a,a可改b
const int a = 10;
const int& b = a;

//a可改b,b不可改a没有修改权限
int a = 10;
const int& b = a;

遇到传参的时候

int a = 10;
const int& b = a;

//传参
//错误 权限放大
void fc(int& x)
{
}

//正确
void fc(int x)
{
}

void fc(const int& x)
{
}

如果要减少拷贝,且x在函数中不变,仅仅是使用值,建议使用

const引用


8. 引用和指针的区别

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  3. 没有NULL引用,但有NULL指针
  4. sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占 4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 有多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

更具体见第五点的汇编代码解释

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凛音Rinne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值