C++简明教程(文章要求学过一点C语言)(7)

embedded/2024/12/22 7:27:13/

C++ 引用、指针与赋值的深度剖析

一、引用的概念

引用是 C++ 中的一个重要特性,它可以看作是变量的别名。引用在创建时必须被初始化,这是引用的一个重要规则。因为引用本身不占用额外的内存空间,它只是已存在变量的别名,所以需要在声明时就指定它所引用的变量。例如:

int num = 10;
int& ref = num;  // ref 是 num 的引用,它们指向相同的内存位置
std::cout << "num 的值:" << num << std::endl;
std::cout << "ref 的值:" << ref << std::endl;
ref = 20;  // 通过引用修改所绑定变量的值
std::cout << "修改后 num 的值:" << num << std::endl;
std::cout << "修改后 ref 的值:" << ref << std::endl;

在上述代码中,ref 被声明为对 num 的引用,对 ref 的任何操作都等同于对 num 的操作,因为它们本质上是同一个内存位置的不同名称。

二、引用与指针的区别

  1. 内存占用与地址表示
    • 引用:引用本身不占用额外的内存空间,它只是已存在变量的别名,与被引用变量共享内存地址。例如上面代码中 ref 的内存地址和 num 是完全相同的,在整个生命周期内,引用一旦初始化,就不能再绑定到其他变量上,始终指向最初绑定的那个变量。
    • 指针:指针是一个独立的变量,它占用内存空间(通常在 32 位系统上为 4 个字节,64 位系统上为 8 个字节),用于存储另一个变量的内存地址。例如:
int num = 10;
int* ptr = &num;  // ptr 是一个指针,指向 num 的内存地址
std::cout << "num 的地址:" << &num << std::endl;
std::cout << "ptr 的值(即 num 的地址):" << ptr << std::endl;

指针可以在程序运行过程中重新指向其他变量的内存地址,具有更大的灵活性,但同时也需要更多的内存来存储指针本身的地址信息。
2. 操作符与语法
- 引用:在声明和使用引用时,使用 & 符号,但这个 & 与取地址操作符的含义不同,它是引用声明的一部分。例如 int& ref = num; 是声明一个引用,而在其他地方使用 ref 时,就像直接使用原变量 num 一样,不需要额外的操作符。
- 指针:使用 * 操作符来访问指针所指向的变量的值,使用 & 操作符来获取变量的地址赋给指针。例如:

int num = 10;
int* ptr = &num;
std::cout << "通过指针访问 num 的值:" << *ptr << std::endl;  // 使用 * 访问指针指向的值
*ptr = 20;  // 通过指针修改所指向变量的值
std::cout << "修改后 num 的值:" << num << std::endl;

指针的操作相对引用来说更加复杂,需要小心使用 *& 操作符,避免出现空指针解引用(即对一个未初始化或无效的指针进行 * 操作)等错误,这可能会导致程序崩溃。

三、引用与赋值的区别

  1. 数据复制与关联
    • 赋值:当进行赋值操作时,如 int a = 5; int b = a;,会将变量 a 的值复制一份赋给变量 b。此时 ab 是两个独立的变量,它们在内存中有各自的存储空间,只是初始值相同。后续对 a 的修改不会影响 b,反之亦然。例如:
int a = 5;
int b = a;
a = 10;
std::cout << "a 的值:" << a << std::endl;  // 输出 10
std::cout << "b 的值:" << b << std::endl;  // 输出 5
- 引用:如前所述,引用是变量的别名,与被引用变量共享内存,对引用的修改就是对原变量的修改,它们之间是一种紧密的关联关系,而不是简单的数据复制。
  1. 用途与场景
    • 赋值:常用于在程序中初始化新变量或者在不同变量之间传递数据副本,特别是当我们需要保留原始数据的独立性,不希望后续的修改相互影响时,就会使用赋值操作。
    • 引用:通常用于函数参数传递和函数返回值,这样可以避免不必要的数据复制,提高程序的效率,同时也可以在函数内部直接修改外部变量的值,实现类似于“双向传递”的效果(但要注意避免滥用,以免使程序逻辑变得复杂难以理解)。

四、通过交换函数对比三者区别

以下是分别使用引用、指针和赋值来实现交换两个变量值的函数示例:

  1. 使用引用实现交换函数
void swapByReference(int& num1, int& num2) {int temp = num1;num1 = num2;num2 = temp;
}int main() {int a = 5;int b = 10;std::cout << "交换前:a = " << a << ", b = " << b << std::endl;swapByReference(a, b);std::cout << "交换后:a = " << a << ", b = " << b << std::endl;return 0;
}

在这个例子中,swapByReference 函数使用引用作为参数,函数内部对参数的修改直接反映在调用函数的实参上,因为引用与实参共享内存,实现了变量值的交换
2. 使用指针实现交换函数

void swapByPointer(int* ptr1, int* ptr2) {int temp = *ptr1;*ptr1 = *ptr2;*ptr2 = temp;
}int main() {int a = 5;int b = 10;std::cout << "交换前:a = " << a << ", b = " << b << std::endl;swapByPointer(&a, &b);std::cout << "交换后:a = " << a << ", b = " << b << std::endl;return 0;
}

这里的 swapByPointer 函数使用指针作为参数,通过解引用指针来访问和修改所指向的变量的值,需要在调用函数时传递变量的地址,实现了与引用类似的交换效果,但语法上更加复杂,需要注意指针的有效性和正确使用,避免出现空指针等问题。
3. 使用赋值实现交换函数(这种方式不太符合常规的交换函数逻辑,但为了对比展示)

void swapByAssignment(int num1, int num2) {int temp = num1;num1 = num2;num2 = temp;std::cout << "函数内交换后:num1 = " << num1 << ", num2 = " << num2 << std::endl;
}int main() {int a = 5;int b = 10;std::cout << "交换前:a = " << a << ", b = " << b << std::endl;swapByAssignment(a, b);std::cout << "交换后:a = " << a << ", b = " << b << std::endl;
}

在这个 swapByAssignment 函数中,虽然在函数内部实现了两个参数值的交换,但由于函数参数是按值传递的,这种交换只是在函数内部的局部变量之间进行,对函数外部的实参 ab 没有影响,这体现了赋值操作只是复制数据,而不会影响原始变量的特性。

五、引用的注意事项

  1. 引用必须初始化:引用在声明时必须被初始化,指向一个已经存在的变量,否则会导致编译错误。例如 int& ref; 是不合法的,必须写成 int num = 5; int& ref = num; 这样的形式。
  2. 不能重新绑定:一旦引用被初始化绑定到一个变量,就不能再重新绑定到其他变量。例如:
int num1 = 5;
int num2 = 10;
int& ref = num1;
// ref = num2;  // 这行代码不是重新绑定,而是通过引用修改 num1 的值为 num2 的值

试图将 ref 重新绑定到 num2 是不允许的,它始终与 num1 保持关联,除非 num1 的生命周期结束(例如 num1 所在的作用域结束),此时 ref 的引用也会失效。

看看其他人的

https://blog.csdn.net/weixin_56935264/article/details/124669712


http://www.ppmy.cn/embedded/147749.html

相关文章

《Python版本的那些事儿》

《Python版本的那些事儿》 一、Python 版本发展历程概述1、Python 1.x 系列简介2、Python 2.x 系列特点与重要版本3、Python 3.x 系列重大更新与各版本亮点 二、Python 不同版本关键特性对比1、语法层面的变化对比2、标准库的更新与差异3、功能特性的拓展与优化对比 三、Python…

【QT实战上手之To Do】

预计实现以下功能&#xff1a; 每个待办事项前都有一个勾选框&#xff0c;可以单独勾选。支持单独删除某一项事项。支持全选删除已勾选的事项。支持清除所有事项。 界面布局 ----------------------------------------- | 输入待办事项 [____________________] | <…

凯酷全科技抖音电商服务的卓越践行者

在数字经济蓬勃发展的今天&#xff0c;电子商务已成为企业增长的新引擎。随着短视频平台的崛起&#xff0c;抖音作为全球领先的短视频社交平台&#xff0c;不仅改变了人们的娱乐方式&#xff0c;也为品牌和商家提供了全新的营销渠道。厦门凯酷全科技有限公司&#xff08;以下简…

你的第一个博客-第一弹

使用 Flask 开发博客 Flask 是一个轻量级的 Web 框架&#xff0c;适合小型应用和学习项目。我们将通过 Flask 开发一个简单的博客系统&#xff0c;支持用户注册、登录、发布文章等功能。 步骤&#xff1a; 安装 Flask 和其他必要库&#xff1a; 在开发博客之前&#xff0c;首…

设计模式-中介模式

背景&#xff08;与外观模式相似&#xff09; 智能家庭中包括各种设备&#xff1a;闹钟、咖啡机、电视机、窗帘。 主人要看电视时&#xff0c;执行以下操作&#xff1a;闹钟响起-》咖啡机做咖啡-》窗帘自动落下-》电视开始播放 传统思路&#xff1a; 闹钟类接收命令&#x…

Laya ios接入goole广告,搭建环境 1

只能说麻烦的一批&#xff0c;会了不难&#xff0c;难在不会 没有mac机&#xff0c;用的mac本&#xff0c;提示----》可能需要你升级macbook系统版本&#xff0c; 1、安装cocoapods sudo gem install cocoapods -V 加上-V&#xff0c;能查看安装进度&#xff0c;记住大写的…

Python拆分Excel - 将工作簿或工作表拆分为多个文件

在日常工作中&#xff0c;我们经常需要处理包含大量数据的Excel文件。这些文件可能包含不同的表格、图表和工作表&#xff0c;使得数据管理和分析变得复杂。为了提高效率和准确性&#xff0c;我们可以将一个Excel文件或其中某一个工作表按需求拆分为多个文件&#xff0c;以便更…

【HTML】DOCTYPE的作用?

HTML 中DOCTYPE的作用&#xff1f; <!DOCTYPE html>是h5的声明。 用于声明当前HTML版本&#xff0c;用来告知web浏览器该文档使用是哪种 HTML 或者 XHTML 规范来解析页面&#xff0c;以便浏览器更加准确的理解页面内容&#xff0c;更加良好地展现内容效果&#xff01; …