C++引用

1.C++ 引用:

一.定义

在 C++ 中,引用是给已存在的变量起的一个别名。引用不是一个新的变量,它与被引用的变量共用同一块内存空间。

二.声明

引用的声明使用 & 符号,例如: int& ref = num; ,这里 ref 就是变量 num 的引用。

三、特点


引用必须在创建时初始化,且一旦初始化,就不能再指向其他变量。
引用在使用时和被引用的变量完全等价,对引用的操作就是对被引用变量的操作。


四、和指针的区别

1.引用在语法层面不开辟空间只是对变量取别名

指针在语法层面开辟空间存放变量

但是从底层汇编的角度看,引用是通过类似指针的方式实现的!


2.引用在声明时必须初始化,而指针可以在任何时候赋值。


3.引用一旦与某个变量绑定,就不能再改变指向,指针则可以随时改变指向。


4.引用没有 NULL 引用,而指针可以为 NULL 。

6.引用在sizeof的结果为引用类型的大小,而指针在sizeof的结果是地址空间所占的大小。

7.引用++表示引用的实体的值+1,而指针+1是指针像后偏移一个类型的大小


五、引用的注意事项


引用不能引用引用,不能引用数组。(引用无法完全替代指针!)但指针也可以取别名
引用的类型必须与被引用变量的类型一致。

我们用引用可以去写一个交换两个数和交换两个指针的函数

//交换两个数
void swap(int&a,int&b)
{
    int tmp = a;
    a = b;
    b = tmp;
}
//交换两个指针
void swap(int*& a, int*& b)
{
    int* tmp = a;
    a = b;
    b = tmp;
}

当然一个数的引用可以有多个,但是它们的地址都是一样的,并且只要其中一个的值改变,其他的值都会改变,并且改变后一致!

同一个域里面不能出现同名!会有歧义

但是不同的域可以!

引用不会去额外开辟空间

2.引用被当作参数

1:(输出型参数)

2.(提高效率)(大对象/深拷贝对象)


3.引用用作返回值

int back(void)
{
    return 3;
}

int main(void) {
    int a = back();
    return 0;
}

这个返回值3是直接给a的吗?

显然不是,编译器会生成一个临时变量(不一定是寄存器,因为寄存器一般是四个字节或者八个字节)

作为back()的返回值,给予a

要临时变量去存放这个3,因为这个3的作用域是在back函数内,出函数就会销毁掉!

那如果我用static呢?

毕竟static修饰的变量存放在静态区,不会因函数销毁而销毁

编译器没有对static专门去处理,也需要一个临时变量去储存,那么有没有不需要临时变量的方式呢?

显然有,就是引返回值用引用(减少拷贝提升效率),比如像下面这样

int& back(void)
{
    static int a = 5;
    a++;
    return a;
}

但是这个地方还需要注意的是,当函数结束后,返回值要还存在,才可以引用返回值,不然就可能造成非法访问!

比如上面用的static修饰的a,是在静态区上,当函数结束后依然存在,不会随着函数栈帧的销毁而销毁,包括全局变量和malloc,realloc的变量都是可以使用引用返回值的!

4.常引用

使用引用的时候,引用的权限可以平移缩小,但是不能变大

比如说上面这串代码,为什么会报错?

因为我们返回的是static修饰的变量,返回的时候要先创建临时变量,再把这个临时变量赋给a,

但是临时变量是具有常性,即(const不可修改性) ,但是&a是可修改性的,从不可改变性变成可改变性权限扩大了,但是引用的权限只能平移或者缩小,因此我们这个地方可以在int&a前面加一个const就行了

就像这样

int back1(void)
{
    static int a = 5;
    a++;
    return a;
}

int main(void) {
    
    const int &a= back1();
    return 0;
}

这个时候引用的权限就算平移了

但是为啥我们在这个地方这样也可以

//返回常量
int back1(void)
{
    static int a = 5;
    a++;
    return a;
}

int main(void) {
    
   int a= back1();
    return 0;
}

因为这个地方我们本质并不是引用,而是把返回值拷贝过来了,而且这个地方我们没有涉及到引用,自然就不用去考虑权限的扩大缩小和平移了!,下图同理

//返回引用
int& back2(void)
{
    static int b = 6;
    b++;
    return b;
}

int main(void) {
    
   int a= back2();//拷贝
   int& b = back2();//权限平移
   const int& c = back2();//权限缩小
    return 0;
}

需要注意的是,不同类型的变量的转换也需要创建临时变量

我们前面说过什么?临时变量具有常性,因此这个地方会非常容易错

int main(void) {
    double a = 1.1;
   // const int& b = a;//不会报错 权限平移
    int& b = a;//会报错 权限扩大了
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值