C++引用

引用概念

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

 如: 孙悟空 又称为 齐天大圣 , 斗战胜佛.

类型& 引用变量名(别名) = 对象;

引用符号就是 &

int a = 10;
int& b = a;
printf("%p\n", &a);
printf("%p\n", &b);

其中 b 就是就是 a 的别名.
打印出来的两个地址也就是相同的.

所以当引用值改变时, 原先的值也会改变

int a = 10;
int& b = a;
cout << a << ": " << b << endl;
b = 20;
cout << a << ": " << b << endl;

a 的值从10 被修改为 20.

引用特性

1. 引用一旦定义了,就必须立即初始化.

一个对象可以有多个引用.

引用的类型需要和被引用的对象类型相同

int a = 10;
int& b; // 在定义是没有初始化, 会报错
int a1 = a;
int a2 = a;
int a3 = a;
// a1, a2, a3 都是 a 的引用, 修改三个中任意一个,
// 另外两个和 a 都会改变

double& c = a; // 这是不可以的, 类型一定要匹配

2. 引用不能被重新赋值给另一个对象.

int a = 10;
int b = 20;
int& c = a;
c = b; // 这条语句的意思是, 将 b 赋值给 c
       // c 还是 a 的引用, 而不是 b 的引用

常引用

顾名思义就是常量的引用.

但是常量具有不可修改性. 所以引用需要加上 const.

const int a = 10;
// int& a1 = a;    // 无法通过编译
const int& a1 = a; // 必须加上 const

使用场景

1. 作为参数

用引用作为函数参数: 

引用的本质是取别名
所以传递参数时, 就不会产生拷贝
和传地址的作用相似
减少拷贝的消耗, 并且也可以在函数内部修改外部对象

void swap(int& a, int& b)
{
    int tem = a;
    a = b;
    b = tem;
}

int a = 10;
int b = 20;
swap(a, b); // 因为参数是引用, 所以 swap 可以将 a 和 b 的值交换
// 这里调用函数传递参数时, 不需要使用 & 符号

2. 作为返回值

引用做返回值
也可以获得函数内部的值

并且在函数外部修改

前提: 引用的变量出了函数之后, 不会被销毁

static int n = 0;
int& func()
{
    n++;
    return n;
}

int& tem = func();
tem = 10;
cout << tem << ": " << n;

局部变量出了作用域就会销毁, 所以这里 n 是静态变量, 修改 tem 也会改变 n.

int& func()
{
    int c = 20;
    return c;
}

这里是不能使用传值返回的.
因为 c 在函数结束时会被销毁,
将 c 的引用返回后,
如果使用会产生野指针的风险.

使用引用作为返回值, 返回的对象在出了作用必须还没有被销毁.

如果函数结束时, 对象已经被销毁了, 就不能使用引用作为返回值

传值和传引用比较 

1. 作为函数参数: 
        传值: 形参实际上是对象的副本, 需要拷贝对象
        传引用: 形参就是对象本身, 不需要拷贝, 减少了拷贝的消耗

2. 作为函数返回值:
        传值: 返回过程中会产生临时对象(中间变量), 然后用这个临时对象去赋值给函数接收值.
        传引用: 返回值并不需要创建临时对象, 省去了创建临时对象的开销

在对象的传递过程中, 引用作为参数和返回值

效率是比传值效率要高的

当对象类型非常大时, 效率就能进一步提高

 引用和指针联系比较

1. 语法上: 
        引用在语法概念上就是一个别名, 本身不开辟空间.
        指针是一个类型, 有自己的空间.

2. 底层实现: 
        引用在底层实际的实现上, 是有空间的
        因为引用本质上就是通过指针来实现的.

场景引用指针
初始化引用一旦定义了,就必须立即初始化指针在定义时可以不初始化
重新赋值引用不能被重新赋值给另一个对象指针可以被重新赋值,指向一个新地址
语法引用使用'&'符号声明: int &b = a;指针使用'*'符号声明: int *a = &b;
与NULL的关系引用不能为NULL,引用必须绑定一个有效的对象指针可以为NULL,表示这个指针不指向任何对象
内存地址引用本身不占用内存空间,它只是对象别名指针本身占用内存空间,存储了对象的地址
类型转换引用在声明初始化时,类型必须匹配,不能进行类型转换指针可以进行类型的转换,如:void* 转换为int *;
使用场景通常用于函数参数的传递,避免复制对象,减少空间消耗用于动态内存分配、数组操作、复杂的数据结构实现等
安全性引用必须绑定到一个对象,所以使用起来相对安全,不容易出现野引用不当使用可能导致野指针、内存泄漏等问题。
sizeof引用结果为引用类型的大小,如: struct student st; sizeof(st)结果为struct student的大小指针始终是地址空间所占字节数(32为平台下就是4个字节)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值