C++零基础(02)——引用类型

引用是C++相对于C扩展的一种类型,其作用是为某个变量定义一个别名

则,通过原变量别名都能操作该对应的内存数据。

一、定义和使用

  • 语法
datatype &ref_name = origin_name;

datatype是数据类型,与origin_name变量的类型一致;ref_name是引用的变量名(别名),origin_name是被引用的变量名(原名称);

如:

int a = 10;
int &a1 = a; // 引用,a1为a的别名

以上定义后,a1为a的别名,意味着,对a1的操作等同于对a的操作,反之亦然。如:

cout << "a:" << a << endl;
cout << "a1:" << a1 << endl;
    
a1 = 20;
cout << "a:" << a << endl;
cout << "a1:" << a1 << endl;

终端输出为:

a:10
a1:10
a:20
a1:20
  • 注意:引用在定义的时就必须初始化,否则会编译报错。如:
int &a1; // error:Declaration of reference variable 'a1' requires an initializer

二、引用的本质

先看引用变量的内存地址。

int a = 10;
int &a1 = a; // 引用,a1为a的别名
// 输出 a和a1的内存地址
cout << &a << ", " << &a1 << endl;

终端打印:0x7ffeefbff5ec, 0x7ffeefbff5ec

可以看出,a和a1两个变量都是“指向”同一个地址的;这样就能解释为什么对a或a1进行操作,能影响另一个。

引用的本质实际上是指针的封装

是一个指向原变量内存地址的指针,封装了内部实现,使用起来相较指针而言更为简单。

三、引用作为函数参数

因为引用是别名的这一特质,在参数传递过程中,可以提高速度减少内存开销;同时函数内部也可以修改实参

  • 语法:

datatype functionName(datatype &param, …)

  • 函数内部修改实参

例: 定义swap函数,实现两个值的交换

void swap(int &a, int &b) {
    // 形参为引用变量,相当于  int &a = a; (=号左边为形参a,=号右边为实参a)
    int tmp = a;
    a = b;
    b = tmp;
}

int main() {
    
    int a = 10;
    int b = 20;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    
    swap(a, b); // 调用交换函数
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
}

终端输出:

a:10
b:20
a:20
b:10

交换实参的值,是对引用传递比较经典的例子,那如果在函数内部不需要修改实参的值,那形参定义为引用或普通变量的区别又是什么呢?

  • 提高传递速度、减少内存开销

    例: 显示一个学生信息

形参为普通变量:

void funShowStudent1(Student s) {
    cout << "姓名:" << s.name << endl;
    cout << "年龄:" << s.age << endl;
    cout << "身高:" << s.height << endl;
    cout << "体重:" << s.weight << endl;
    // 打印其他信息。
}

形参为引用变量:

void funShowStudent2(Student &s) {
    cout << "姓名:" << s.name << endl;
    cout << "年龄:" << s.age << endl;
    cout << "身高:" << s.height << endl;
    cout << "体重:" << s.weight << endl;
    // 打印其他信息。
}

main函数中调用:

int main() {

    Student stu;
    strcpy(stu.name, "binson");
    stu.age = 24;
    stu.height = 172.5;
    stu.weight = 68.8;
    
    funShowStudent1(stu);
    funShowStudent2(stu);
}

终端输出:

main_stu的内存地址:0x7ffeefbff5b8
show1_stu的内存地址:0x7ffeefbff510
姓名:binson
年龄:24
身高:172.5
体重:68.8
show2_stu的内存地址:0x7ffeefbff5b8
姓名:binson
年龄:24
身高:172.5
体重:68.8

观察可得知,普通类型形参的地址不同于实参变量的地址;所以funShowStudent1函数在调用过程中,形参需开辟新的内存存放数据。而引用变量使用实参同一个内存。

如果涉及到深拷贝情况更复杂,在后续章节记录。

因为在函数内部不需要对实参进行修改,所以形参使用常引用进行传递,提高安全性。

如下:const Student &s

void funShowStudent(const Student &s) {
    cout << "姓名:" << s.name << endl;
    cout << "年龄:" << s.age << endl;
    cout << "身高:" << s.height << endl;
    cout << "体重:" << s.weight << endl;
    // 打印其他信息。
    
    // 不能对常引用变量进行修改
    //s.height = 180.0; // error:Cannot assign to variable 's' with const-qualified type 'const Student &' (aka 'const _student &')
}

四、 引用作为函数返回值

  • 语法

datatype& functionName(…)

例:

int& funExample2() {
    int a = 10;
    a += 10;
    return a; // warning:Reference to stack memory associated with local variable 'a' returned
}

大写的错误: 不能返回局部变量的引用。这个错误编译时只会报警告,在运行时会程序奔溃。

不能返回局部变量的引用,但可以返回,静态变量,全局变量的引用。如:

int& funExample3() {
    static int a = 10; // 静态变量
    a += 10;
    return a; 
}

在main函数中调用:

int &res = funExample3();
cout << res << endl;

总结:

  • 引用变量的数据类型必须与原数据类型一致。
  • 引用声明的时候就必须初始化,且不能更改引用对象
  • 可对引用再次引用。多次引用的结果,是某一个变量具有多个别名。
  • 引用可作为函数的参数或返回值,返回值不能返回局部变量的引用。

本文示例代码

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值