九.C++ 对引用的学习
一.基本概念
引用即内存的别名
int a = 10;
int& b = a;
引用本身不占用内存,并非实体,对引用的所有操作都是在对目标内存进行操作
引用必须初始化,且不能更换对象
int c = 5;
b = c; // × 仅仅是在对引用的目标内存进行赋值
#include <iostream>
using namespace std;int main() {int mm1 = 20; // 1. 定义整型变量mm1并初始化为20int& mm2 = mm1; // 2. 定义整型引用mm2,绑定到mm1int mm3 = 15; // 3. 定义整型变量mm3并初始化为15mm2 = mm3; // 4. 将mm3的值赋给mm2(即mm1)cout << "mm1: " << mm1 << endl; // 输出 15cout << "mm2: " << mm2 << endl; // 输出 15cout << "mm3: " << mm3 << endl; // 输出 15return 0;
}
详细执行过程:
-
int mm1 = 20;
-
定义一个整型变量
mm1
,并将其初始值设为20
。 -
内存中:
mm1
存储的值是20
。
-
-
int& mm2 = mm1;
-
定义一个整型引用
mm2
,并将其绑定到mm1
。 -
引用
mm2
并不是一个新的变量,而是mm1
的别名(另一个名字)。 -
此时,
mm2
和mm1
指向同一块内存,修改mm2
就是修改mm1
,反之亦然。
-
-
int mm3 = 15;
-
定义一个整型变量
mm3
,并将其初始值设为15
。 -
内存中:
mm3
存储的值是15
。
-
-
mm2 = mm3;
-
将
mm3
的值(15
)赋给mm2
。 -
由于
mm2
是mm1
的引用,这实际上是将15
赋给mm1
。 -
执行后:
-
mm1
的值变为15
。 -
mm2
的值也变为15
(因为它是mm1
的引用)。 -
mm3
的值仍然是15
(不受影响)。
-
-
最终结果:
-
mm1
的值:15
(被mm2 = mm3
修改) -
mm2
的值:15
(因为它是mm1
的引用) -
mm3
的值:15
(保持不变)
输出:
mm1: 15
mm2: 15
mm3: 15
关键点总结:
-
引用(
&
)的本质:-
引用是变量的别名,不是独立的变量。
-
int& mm2 = mm1;
表示mm2
是mm1
的另一个名字,两者共享同一块内存。
-
-
赋值操作的影响:
-
mm2 = mm3;
实际上是将mm3
的值赋给mm1
(因为mm2
是mm1
的引用)。 -
引用本身没有独立的内存空间,赋值操作会直接影响它绑定的变量。
-
-
与指针的区别:
-
如果是
int* p = &mm1; *p = mm3;
,效果和引用类似,但引用更简洁且不能重新绑定。 -
引用一旦绑定后不能更改绑定的对象,而指针可以指向不同的对象。
-
引用本身一旦绑定后不能重新绑定到另一个对象,引用不能改变
关于 “引用不能改变” 的说法需要更精确的解释。实际上,引用本身一旦绑定后不能重新绑定到另一个对象,但 引用绑定的对象的内容是可以改变的。这是两个不同的概念:
1. 引用的“不可变性”(不能重新绑定)
-
引用一旦初始化后,不能指向其他变量:
-
引用在声明时必须初始化,并且之后不能更改它绑定的对象。
-
例如:
-
int a = 10;
int b = 20;
int& ref = a; // ref 绑定到 a
ref = b; // 这是修改 ref 绑定的对象 a 的值,不是改变 ref 的绑定!// ref = &b; // 错误!不能重新绑定 ref 到 b(C++ 不允许)
-
关键点:
ref = b
是把b
的值赋给a
(因为ref
是a
的引用),而不是让ref
指向b
。
2. 引用绑定的对象的内容可以改变
引用本身是别名,修改引用就是修改它绑定的对象
-
例如:
int a = 10;
int& ref = a; // ref 是 a 的别名
ref = 20; // 修改 ref 就是修改 a,a 现在是 20
常见误区澄清
-
误区:“引用不能改变” → 实际上是指 引用不能重新绑定,但可以修改它绑定的对象的内容。
正确说法:
-
引用 不能重新绑定(不能指向其他对象)。
-
引用 可以修改它绑定的对象的内容(因为它是别名)。
-
总结
-
引用一旦绑定后不能重新绑定(不能指向其他变量),这是它的“不可变性”。
-
引用绑定的对象的内容可以改变(通过引用直接修改)。
mm2 = mm3
-
mm2
是mm1
的引用,所以mm2 = mm3
就是mm1 = mm3
。 -
修改的是
mm1
的值,mm2
仍然绑定到mm1
(不能重新绑定)。
二.引用的常属性必须和目标的常属性“一致”(个别情况也可以不一致)
const int e = 10;
int& f = e; // ×
const int& g = e; // √
可以限定更加严格(别名可以比真名更加严格)
int a = 10;const int& h = a; // OK
三.const 修饰一个常量(常引用)
在 C++ 中,const
引用(const T&
)是一种非常重要的特性,它结合了引用的效率和 const
的安全性。
1. 基本概念
-
const
引用:-
是一个对常量对象的引用,不能通过该引用修改所绑定的对象。
-
语法:
const T& ref = obj;
-
作用:提供对对象的只读访问,同时避免拷贝(与普通引用类似)。
与普通引用的区别:
-
特性 | 普通引用 (T& ) | const 引用 (const T& ) |
---|---|---|
能否修改对象 | 可以修改绑定的对象 | 不能修改绑定的对象 |
绑定对象类型 | 必须绑定可修改的对象 | 可以绑定 const 或非 const 对象 |
安全性 | 可能意外修改数据 | 提供只读访问,更安全 |
2. 核心知识点
(1) const
引用可以绑定到 const
和非 const
对象
-
可以绑定到非
const
对象(提供只读访问):
int x = 10;
const int& ref = x; // ref 是 x 的 const 引用
// ref = 20; // 错误!不能通过 ref 修改 x
-
可以绑定到
const
对象(合法且安全):
const int y = 20;
const int& ref = y; // ref 是 y 的 const 引用
// ref = 30; // 错误!y 本身就是 const
-
普通引用不能绑定到
const
对象:
const int z = 30;
int& ref = z; // 错误!普通引用不能绑定 const 对象
(2) const
引用可以延长临时对象的生命周期
-
临时对象(如函数返回值、表达式结果)通常只能绑定到
const
引用 -
用途:避免不必要的拷贝,同时保证安全性(不能修改临时对象)
10; // 声明周期很短,正常执行过了封号后 10这个内存地址就不在了int& ri = 10; // 报错 非常引用的初始值必须为左值,普通引用不能绑定临时对象const int& ri = 10; // 正确,有了这个别名之后,声明周期就变长了,会跟着别名的生命周期改变
了解一个左值和右值的概念:
具体名字的内存,能够取地址 --》 左值 (非常左值[无const修复] | 常左值[有const修复])
匿名内存,不能取地址值 --》 右值 (认为直接更改右值没有意义) 比如 10;
常引用可以作为任何东西的别名
特点:
1.引用可以延长右值的生命周期
2.常引用 即 万能引用
3.引用的生命周期不能长于目标
int a = 10;int& ra = a; // OK 引用ra可以是a的别名
const int& ri = a; // OK 常引用 ri 可以是 a的别名const int b = 20;int& bb = b; // ERROR const int& bb = b; // OK 常引用bb可以是常量b的别名const int& rf = 10; // OK 常引用rf可以是常量10的别名int foo(){}const int& hg = foo(); // OK
(3) const
引用作为函数参数(推荐用法)
-
传递大对象时避免拷贝,同时防止函数内部修改参数:
void printValue(const std::string& str) {// str = "new value"; // 错误!不能修改std::cout << str << std::endl;
}int main() {std::string s = "Hello";printValue(s); // 传递 const 引用,避免拷贝
}
优势:
高效(无拷贝)。
安全(函数不能意外修改参数)。
(4) const
引用与返回值
-
函数返回
const
引用:-
可以避免返回临时对象的拷贝,同时防止调用者修改返回值:
-
const std::string& getString() {static std::string s = "Hello";return s; // 返回 static 变量的 const 引用
}
注意:如果返回局部变量的引用,会导致悬空引用(未定义行为)!
const std::string& getLocalString() {std::string s = "Hello";return s; // 错误!s 是局部变量,函数结束后被销毁
}
(5) const
引用与重载
-
const
引用可以区分重载函数:
void func(const int& x) { std::cout << "const ref" << std::endl; }
void func(int& x) { std::cout << "non-const ref" << std::endl; }int main() {int a = 10;const int b = 20;func(a); // 调用非 const 版本func(b); // 调用 const 版本
}
-
编译器会根据参数是否为
const
选择正确的重载版本。
(6) const
引用与移动语义
-
const 引用不能用于移动语义:
-
移动语义需要修改源对象(“窃取”资源),而
const
引用禁止修改:
-
std::string s = "Hello";
const std::string& ref = s;
// std::string moved = std::move(ref); // 错误!ref 是 const
正确做法:传递非 const
引用或值:
std::string moved = std::move(s); // 正确
3. 最佳实践
-
优先使用
const
引用传递参数:-
避免拷贝,同时保证函数不会意外修改参数。
-
示例:
-
void process(const std::vector<int>& data) { ... }
-
返回
const
引用时注意生命周期:
-
只能返回全局/静态对象的引用,不能返回局部变量的引用。
-
区分
const
和非const
重载:
-
提供更灵活的接口(如
std::vector
的operator[]
有const
和非const
版本)。
-
避免滥用
const
引用:
-
如果需要修改参数,使用普通引用。
-
如果需要返回可修改的对象,返回值或非
const
引用。
4. 常见误区
-
误区 1:“
const
引用不能绑定到临时对象”-
纠正:
const
引用可以绑定到临时对象(普通引用不能)。
-
-
误区 2:“
const
引用可以修改绑定的对象”-
纠正:
const
引用不能修改绑定的对象(这是它的核心特性)。
-
-
误区 3:“
const
引用总是比值传递好”-
纠正:如果对象很小(如
int
),值传递可能更高效(避免引用开销)。
-
5. 总结
特性 | const 引用 (const T& ) |
---|---|
绑定对象 | 可以绑定 const 或非 const 对象 |
能否修改对象 | 不能(提供只读访问) |
临时对象绑定 | 可以绑定临时对象(普通引用不能) |
函数参数 | 推荐用于大对象,避免拷贝且保证安全性 |
返回值 | 可以返回 const 引用(但需注意生命周期) |
重载区分 | 可以与非 const 引用重载 |
移动语义 | 不能用于移动语义(因为不能修改源对象) |
核心原则:
-
const
引用 = 高效 + 安全(避免拷贝,防止意外修改)。 -
普通引用 = 高效 + 可修改(需要修改参数时使用)。
-
值传递 = 简单 + 安全(小对象或需要独立副本时使用)。
建议:合理使用 const
引用可以显著提升代码的性能和安全性!
相关文章:
九.C++ 对引用的学习
一.基本概念 引用即内存的别名 int a 10; int& b a; 引用本身不占用内存,并非实体,对引用的所有操作都是在对目标内存进行操作 引用必须初始化,且不能更换对象 int c 5; b c; // 仅仅是在对引用的目标内存进行赋值 #include <ios…...

探秘鸿蒙 HarmonyOS NEXT:实战用 CodeGenie 构建鸿蒙应用页面
在开发鸿蒙应用时,你是否也曾为一个页面的布局反复调整?是否还在为查 API、写模板代码而浪费大量时间?今天带大家实战体验一下鸿蒙官方的 AI 编程助手——CodeGenie(代码精灵) ,如何从 0 到 1 快速构建一个…...

art-pi2 上手记录(二)
功能比较庞杂,写得不好,抛砖引玉 预备知识 stm32 默认从主闪存0x08000000启动 art-pi2的psram 映射0x90000000 art-pi2的8线ospi flash 映射0x70000000 stm32h7比较灵活,通过修改选项字节,可以实现从 0x0000 0000 到 0x3FFF 0…...

数据库SQLite基础
SQLite的存储结构 --->B树 大型数据库 :Oracle 中型数据库 :Server是微软开发的数据库产品,主要支持windows平台 小型数据库 : MySQL是一个小型关系型数据库管理系统。开放源码 (嵌入式不需要存储太多数据) 一、SQLite基础 SQLite的源代码…...

1.3 古典概型和几何概型
文章目录 古典概型模型(等可能模型)几何概型 古典概型模型(等可能模型) 两个条件: 1) 有限个样本点 2) 等可能性 例题: 设有n个人,每个人都等可能地被分配到N个房间中的任一间(n≤N), 求下列事件的概率: (1)某指定的n间房…...

html-pre标签
我们都知道在常见标签里面的文字的格式是不会显示的,比如你打了多个空格,但却不会显示,而pre标签会显示。 主要特点: 保留空格和换行:在 <pre> 标签内,HTML 会保留所有的空格、换行符和制表符等格式…...

【WPF】WPF 项目实战:用ObservableCollection构建一个可增删、排序的管理界面(含源码)
💡WPF 项目实战:构建一个可增删、排序的光源类型管理界面(含源码) 在实际的图像处理项目中,我们经常需要对“光源类型”进行筛选或管理。今天我们来一步步构建一个实用的 WPF 界面,实现以下功能࿱…...

MCU_IO驱动LED
注意事项: 1、亮度要求较高的情况下,不能由IO直接驱动LED MCU_IO引脚输出的电压和电流较弱,如果对光的亮度有要求的话,需要使用三极管来驱动。 MCU_IO的电压一般为3.3V或者5V,输出电流一般10mA-25mA。 2、不同颜色…...

上门预约行业技术方案全解析:小程序、App还是H5?如何选择?
上门按摩行业这几年确实火,但千万别以为随便买个系统、招几个技师就能赚钱。作为一家深耕10年软件开发的公司,我们做了四五年上门按摩系统,见过太多人头脑一热冲进来,结果血本无归。 如果你真的想做上门按摩,先想清楚这…...
Java 集合面试题 PDF 及常见考点解析与备考指南
为了帮助你更好地学习Java集合相关知识,我将围绕Java集合面试题展开,介绍常见的技术方案及应用实例。这些内容涵盖了集合框架的基本概念、常见集合类的特点与使用场景,以及在实际开发中可能遇到的问题及解决方案。 Java集合面试题࿱…...

Java 大视界 -- 基于 Java 的大数据分布式计算在蛋白质组学数据分析中的加速与优化(255)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
如何通过外网访问内网?哪个方案比较好用?跨网远程连接网络知识早知道
广域网(英语:Wide Area Network,缩写为 WAN),又称外网、公网。是连接不同地区局域网或城域网计算机通信的远程网。 局域网(LAN),全称为Local Area Network,指在较小的地理区域内,通…...

Vue.js教学第十八章:Vue 与后端交互(二):Axios 拦截器与高级应用
Vue 与后端交互(二):Axios 拦截器与高级应用 在上一篇文章中,我们学习了 Axios 的基本用法,包括如何发送不同类型的 HTTP 请求以及基本的配置选项。本文将深入剖析 Axios 的拦截器功能,探讨请求拦截器和响应拦截器的作用、配置方法和应用场景,通过实例展示如何利用拦截…...
C#中datagridview单元格value为{}大括号
使用数据库查询结果绑定datagridview数据源后,在对单元格的值进行处理的过程中出现报错,包括直接多cell.value.ToString()也报错,调试发现该单元格Value为“{}”,与null或""对比判断都没有结果,可使用Conver…...
46、web实验-遍历数据与页面bug修改
46、web实验-遍历数据与页面bug修改 在Web开发中,遍历数据和修改页面bug是常见的任务。以下是关于这两个主题的讲解: ### 一、遍历数据 **目的**:在页面上动态展示数据,例如用户列表、商品信息等。 **常用方法**: ####…...
华为OD机试_2025 B卷_数组去重和排序(Python,100分)(附详细解题思路)
题目描述 给定一个乱序的数组,删除所有的重复元素,使得每个元素只出现一次,并且按照出现的次数从高到低进行排序,相同出现次数按照第一次出现顺序进行先后排序。 输入描述 一个数组 输出描述 去重排序后的数组 用例 输入1,3,…...

云计算 Linux Rocky day03(which、快捷键、mount、家目录、ls、alias、mkdir、rm、mv、cp、grep)
云计算 Linux Rocky day03(which、快捷键、mount、家目录、ls、alias、mkdir、rm、mv、cp、grep) 目录 云计算 Linux Rocky day03(which、快捷键、mount、家目录、ls、alias、mkdir、rm、mv、cp、grep)1.which找到命令所对应的程序…...
gh hugging face使用
install sudo dpkg -i gh_2.74.0_linux_amd64.deb gh auth login gh auth login ? Where do you use GitHub? GitHub.com ? What is your preferred protocol for Git operations on this host? HTTPS ? Authenticate Git with your GitHub credentials? Yes ? How wo…...
SQL Server全局搜索:在整个数据库中查找特定值的高效方法
SQL Server全局搜索:在整个数据库中查找特定值的高效方法 一、需求背景:为什么需要数据库全局搜索? 在数据库管理和开发过程中,我们经常会遇到这样的场景: 只记得某个数据值,但忘记了它所在的表或列需要…...

JVM 内存溢出 详解
内存溢出 内存溢出指的是内存中某一块区域的使用量超过了允许使用的最大值,从而使用内存时因空间不足而失败,虚拟机一般会抛出指定的错误。 在Java虚拟机中,只有程序计数器不会出现内存溢出的情况,因为每个线程的程序计数器只保…...
Qt 5.12 上读取 .xlsx 文件(Windows 平台)
推荐最优方案:使用 QXlsx 库 QXlsx 是一个基于 Qt 的开源库,专门用于读写 .xlsx 文件,适用于 Qt 5.12,且无需依赖 Microsoft Excel 或 COM 对象。以下是其优势与实现步骤: 优势 跨平台:QXlsx 不依赖 Mic…...

虚拟机CentOS 7 网络连接显示“以太网(ens33,被拔出)“、有线已拔出、CentOS7不显示网络图标
文章目录 一、问题描述二、解决方法1、查看网络连接方式2、开启相关服务3、确认虚拟机网络连接 一、问题描述 问题描述:在VmWare中安装CentOS7, 启动后界面不显示网络的图标。 在GONE桌面—》设置中找到网络设置,发现显示线缆已拔出。 二、解决方法 …...

Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(六):图片上传交互功能
在 《Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(五)》 中,完成了语音交互功能的优化。本文作为该系列教程的第六篇,将聚焦于图片上传功能的开发。通过集成图片上传与预览能力,我们将进一步完善 AI…...

传统的将自然语言转化为嵌入向量的核心机制是:,将离散的语言符号转化为连续的语义向量,其核心依赖“上下文决定语义”的假设和神经网络的特征提取能力。
传统的将自然语言转化为嵌入向量的核心机制是:,将离散的语言符号转化为连续的语义向量,其核心依赖“上下文决定语义”的假设和神经网络的特征提取能力。 传统的将自然语言转化为嵌入向量(Word Embedding)的核心机制是分布式语义假设(Distributional Semantics Hypothesis…...
【前端】每日一道面试题6:解释Promise.any和Promise.allSettled的使用场景及区别。
Promise.any() 和 Promise.allSettled() 是 JavaScript 中用于处理异步操作的两种不同策略的 Promise 组合器,它们的核心区别在于逻辑目标与结果处理方式: 1. Promise.any() 使用场景: 需要获取 首个成功结果(类似竞速成功优先&…...
wordpress+woocommerce电商平台搭建方案的优势分析
以下是WordPress WooCommerce电商平台搭建方案的优势分析: 技术架构与功能扩展优势 强大的插件生态系统:WordPress拥有超过58000个插件,WooCommerce作为其中最受欢迎的电商插件,提供了丰富的功能扩展选项,如支持超过…...

玄机-日志分析-IIS日志分析
1.phpstudy-2018站点日志.(.log文件)所在路径,提供绝对路径 2.系统web日志中状态码为200请求的数量是多少 3.系统web日志中出现了多少种请求方法 4.存在文件上传漏洞的路径是什么(flag{/xxxxx/xxxxx/xxxxxx.xxx} 5.攻击者上传并且利用成功的webshell的文件名是什…...
IDEA:配置 Git 需要完成 Git 路径设置、账号认证以及仓库关联三个主要步骤
一、验证 Git 是否已安装 检查 Git 版本(Windows/Linux/Mac): 打开终端 / 命令提示符,输入: git --version若未安装,下载并安装 Git 二、在 IDEA 中配置 Git 路径 打开设置: Windows/Linux&a…...
PHP 复制商品扩展实操:轻松切换一号通、99api ,实现商品复制功能
目前已有一号通、99api复制商品扩展 复制商品扩展入口 namespace crmeb\services\copyproduct;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use think\facade\Config; use think\Container;/*** Class Product* package crmeb\services\copyp…...

【办公类-104-01】20250606通义万相50分一天用完,通义万相2.1专业版测试
背景需求: 昨天打开通义万相,发现分数降低到3位数,原来时1500.仔细看,原来每天的50分,只有1天有效期了。 用掉试试,用的是之前的30天积分,还是今天的1天积分 纯白色背景,卡通简笔画…...