初识引用 + 引用和指针的区别

引用并非定义一个新的变量,而是为一个已经存在的变量起一个别名

虽然底层是通过指针实现的,但是和指针不一样,无需另外开辟空间,在某些场景下,使用引用可以减少拷贝


目录

一、引用的定义

二、引用的特性

1、 引用的时候必须初始化

2、 引用只能绑定一个实体

3、  一个实体可以有多个引用(别名)

三、引用的应用场景

1、引用传参

2、引用返回

四、指针和引用的区别 

1、概念的角度

2、初始化的角度

(1)区别一:引用必须初始化,指针没有要求

(2)区别二:引用很专一,指针很花心

3、使用的角度

(1)区别三:指针需要显式解引用,引用编译器自己处理

(2)区别四:引用比指针使用起来相对安全

(3)区别五:使用引用无需开辟空间,但是指针需要通过开空间,被赋予空间地址

五、验证引用的底层是指针实现的

六、引用的数据类型转换

(1)  普通数据类型转换

 (2) 引用的数据类型转换


一、引用的定义

数据类型&  别名 = 实体名 

=》这里的 & 不是取地址,相当于指针声明时的 *,标识现在声明的是一个引用变量

int main()
{
    int a = 10;
    int& b = a;        //这里的& 代表声明一个引用

    int* p = &a;       //这里的& 代表取地址
}

二、引用的特性

1、 引用的时候必须初始化

既然是起别名,那么使用引用就必须要知道为谁 起别名

int main(){
    int a = 10;
    int& b = a;    //为a起别名,或者说绑定的实体是a
    return 0;
}

2、 引用只能绑定一个实体

如果b绑定了实体 a,再去绑定实体 c,那么使用b的时候,应该使用哪个实体呢

3、  一个实体可以有多个引用(别名)

在家可以有小名,在外可以有绰号,在公司可以有职称

int main(){
    int a = 10,c = 20;
    int& b = a;        //b绑定的实体是a
    int& c = a;        //c绑定的实体是a
                       //b、c都是a的引用,相当于b是在家的小名,c是在外的绰号
    return 0;
}

三、引用的应用场景

1、引用传参

最简单的例子就是交换两个变量的值

//通过引用 交换两个变量的值
void Swap(int& x,int& y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

int main(){
    int a = 10,b = 20;
    Swap(a,b);
    return 0;
}

在调用Swap函数时,一一对应原则,把 a 给了Swap的第一个参数,相当于 int& x = a

x 这个时候就可以看作是a的别名,改变 x 就可以改变 a

y 也是同理

当然,如果这里使用指针的话,可以达到同样的效果

// 通过指针交换两个变量的值
void Swap(int* x, int* y)
{
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

int main(){
    int a = 10,b = 20;
    Swap(&a,&b);
    return 0;
}

2、引用返回

详见我的另一篇博客

函数引用返回底层分析 —— 栈帧创建与销毁_abs(ln(1+NaN))的博客-CSDN博客主要说明了栈的创建和销毁过程,同时说明引用返回的使用范围 应用:引用传参、引用返回这里着重讲引用返回,在说引用返回之前,先说说函数返回的底层实现1、函数返回底层实现(1)准备工作我们先准备一段简单的代码#include <stdio.h>int Add(int x,int y){ int c = x + y; return c;}int main(){ int a = 10; in...https://blog.csdn.net/challenglistic/article/details/123537888?spm=1001.2014.3001.5501

四、指针和引用的区别 

1、概念的角度

        引用 =======》 一个变量的别名

        指针 =======》 一个变量的地址

2、初始化的角度

(1)区别一:引用必须初始化,指针没有要求

int a = 10;
int& b = a;     //b需要指明是哪个变量的别名

int* a;       //指针不作要求

引用:代表起别名,需要指明是哪个变量的别名

指针:代表地址,可以在需要使用的时候再赋予空间地址

(2)区别二:引用很专一,指针很花心

int main(){
    int a = 10,c = 20;
    int& b = a;        
    
    int* p = &a;    //p指向a
    p = c           //p指向c
}

引用 ======》 绑定一个实体以后,不能再绑定其他实体;

指针 ======》 可以随时改变地址以及地址指向的内容

3、使用的角度

(1)区别三:指针需要显式解引用,引用编译器自己处理

int Test1(int* p)
{
    *p = 10;    //解引用才能使用
}

int Test2(int& p)
{
    p = 10;    //可以直接使用
}

(2)区别四:引用比指针使用起来相对安全

(3)区别五:使用引用无需开辟空间,但是指针需要通过开空间,被赋予空间地址

int main(){
    int a = 10;
    int& b = a;
    b = 20;            //修改实体a的值

    int* p;            //一开始可以无需初始化
    p = new int[1];    //分配 10个int类型的空间   
    *p = 20;           
}

五、验证引用的底层是指针实现的

我们以交换两个变量的值为例,一个使用引用实现,一个使用指针实现

我们通过反汇编来验证

int main(){
    int a = 10;
    int& b = a;    //b绑定实体a
    int* p = &a;    //p获取a的地址,指向a的空间
    return 0;
}

lea:表示取地址,取 a 的地址放入寄存器eax

mov:表示赋值,把eax的地址赋值给 b

 由此可见,引用的底层依然是地址的传递

六、引用的数据类型转换

(1)  普通数据类型转换

有的时候我们会遇到下面这种情况

int main(){
    double d = 3.14;
    int i = d;        //小数部分被舍弃,把整数部分赋值给i
}

从double ==> int,数据类型转换的时候,发生了数据截短,d 的小数部分被舍弃了,d 的整数部分赋值给 i

这个过程中发生了什么??

===》

d 把整数部分取出来,赋值给一个临时变量,然后再把这个临时变量赋值给 i

 (2) 引用的数据类型转换

int main(){
    double d = 3.14;
    int& i = d;        //小数部分被舍弃,把整数部分赋值给i
}

 

单纯的添加一个& ,程序会报错

注意!!!

这里 i  绑定的实体不是 d,而是临时变量!!

临时变量是const类型的,但是 引用(别名)的类型是 int,权限扩大,所以会报错

解决方法是 把引用类型也变成 const类型

int main(){
    double d = 3.14;
    const int& i = d;        //小数部分被舍弃,把整数部分赋值给i
}


 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 引用指针都是 C 语言中用于处理变量地址的概念,但它们有一些区别引用是一个变量的别名,它与原变量共享同一个地址,可以直接访问原变量的值,而不需要使用解引用操作符。指针是一个变量,它存储了另一个变量的地址,需要使用解引用操作符才能访问原变量的值。此外,引用在定义时必须初始化,而指针可以先定义再初始化。 ### 回答2: 引用(Reference)和指针(Pointer)是C++中两种不同的方式来访问内存中的数据。 首先,从语法角度来说,引用是在定义时直接与已存在的变量进行关联,而且一旦关联了某个变量,就不能再改变关联对象。指针则是变量,用来存储某个变量的内存地址,可以通过改变指针的值来指向不同的对象。 其次,从使用方式来说,引用使用起来更加简洁和直观。我们可以通过引用直接使用被关联变量的值,并且不需要使用解引用操作符。指针则需要使用解引用操作符来获取被指向对象的值。 再次,从安全性角度来说,引用相对指针更加安全。因为引用在定义时必须与已存在的变量进行关联,而且不能关联空值,所以不存在空指针的问题。指针则可能存在空指针的情况,使用时需要进行判空操作,以防止程序崩溃或发生未定义的行为。 最后,从底层机制来说,引用在编译器层面就进行了地址的运算,所以引用的性能开销更小。指针在使用时需要进行取地址和解引用的操作,相对而言开销更大。 综上所述,引用指针在语法、使用方式、安全性和底层机制上都有一些区别。在实际开发中,我们可以根据具体需求选择使用引用或者指针。 ### 回答3: 引用指针在C++中都用于访问和操作内存中的数据,但它们之间有一些重要的区别。 1. 定义方式:引用是在声明时使用&符号来定义的,例如int& ref = num;而指针是通过在声明时使用*符号来定义的,例如int* ptr = &num;引用必须在声明时进行初始化,而指针可以在后续的代码中进行初始化或者改变所指向的对象。 2. 空值:指针可以被设置为NULL,表示不指向任何有效的内存地址。而引用必须指向一个已经存在的对象,引用本身不会成为一个空值。 3. 内存管理:指针可以通过使用new和delete关键字进行动态内存的分配和释放,从而允许动态地创建和销毁对象。而引用必须在创建时就指向一个已经存在的对象,并且不能通过引用来动态地创建或销毁对象。 4. 操作方式:引用在使用时不需要进行解引用操作,即可以直接对引用进行操作,编译器会自动将引用指向的对象进行解引用。而指针需要通过解引用操作符*来访问指针指向的内存。 5. 常量:指针可以被声明为const,表示指针本身是一个常量,而引用不能被声明为const,因为引用本身已经是一个常量。 总的来说,引用指针都可以用于操作和访问内存中的数据,但引用更简洁、更安全,而指针更灵活、更复杂。使用时需要根据具体的需求和场景来选择合适的方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值