【C++掌中宝】走进C++引用的世界:从基础到应用

在这里插入图片描述

文章目录

  • 引言
  • 1. 基础概念
  • 2. 引用与指针的区别
  • 3. 引用的应用场景
    • 3.1 引用作为函数参数
    • 3.2 引用作为函数返回值
    • 3.3 常引用(const引用)的使用
    • 3.4 引用与多态
  • 4. C++ 引用的优缺点
  • 5. 引用的注意事项与常见陷阱
  • 6. 总结
  • 结语

引言

C++ 引用是编写高效、简洁代码的重要工具。与指针类似,引用允许程序员以间接方式访问数据,但其使用方式更为安全和简便。在这篇博客中,我们将深入探讨 C++ 中引用的概念、特性以及使用方式,帮助你更好地理解和使用引用。

1. 基础概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵,宋江叫"铁牛",江湖上人称"黑旋风";林冲,外号豹子头;

在这里插入图片描述

因此对引用的任何操作都会直接影响原变量。格式如下:

类型& 引用别名 = 引用对象;

引用使用 & 符号声明,例如:

int a = 10;
int& ref = a;

在上面的例子中,refa 的引用,二者共享同一块内存区域。修改 ref 的值会直接改变 a 的值。

引用的核心特性:

  • 必须初始化:引用在声明时必须绑定到某个变量,且不能更改绑定的对象。
  • 多引用:一个变量可以有多个引用
  • 不占用额外内存:引用和原变量共用同一内存空间。
  • 引用与变量操作一致:对引用的操作会反映在其绑定的变量上。

2. 引用与指针的区别

C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。

引用与指针都能实现间接访问,但二者存在以下不同点:

区别引用指针
初始化必须初始化可以延迟初始化
是否可更改指向不可更改可以更改
是否可为空不能为空(NULL)可以为空(NULL)
使用方式无需解引用符号需使用解引用符号
sizeof中的含义结果为引用类型的大小始终是地址空间所占字节个数(32位平台下占4个字节,64位平台下占8个字节)

引用的优势在于语法简洁且更安全,而指针则更灵活,但容易引发空指针或野指针问题。(从底层汇编的角度来看,引用也是用指针实现的,在底层实现上引用实际是有空间的

我们来看看引用和指针的汇编代码对比

在这里插入图片描述

3. 引用的应用场景

引用在 C++ 编程中有广泛应用,尤其是在函数参数传递和返回值中。以下是几个常见应用场景:

3.1 引用作为函数参数

引用传递能避免值传递时的拷贝操作,提升效率,尤其在处理大对象时。例如:

void modify(int &x) {x = 10;  // 修改外部变量
}

函数 modify 直接修改了实参 x,而不是传递一个副本。

3.2 引用作为函数返回值

函数返回引用能够避免创建副本,直接操作外部数据:

int& getElement(int arr[], int index) {return arr[index];
}

返回数组元素的引用,使外部可以直接修改数组内容。

总结

  • 引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。

  • 引用传参跟指针传参功能是类似的,引用传参相对更方便一些。

  • 引用返回值的场景相对比较复杂,我们在这里简单讲了一下场景,还有一些内容后续类和对象章节中会继续深入讲解。

  • 引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向,Java的引用可以改变指向。

  • 一些主要用C代码实现版本数据结构教材中,使用C++引用替代指针传参,目的是简化程序,避开复杂的指针,但是很多同学没学过引用,导致一头雾水。

3.3 常引用(const引用)的使用

常引用 (const) 用于避免修改原数据,可以理解为只读型同时可以引用常量或临时对象。例如:

void display(const int &x) {std::cout << x << std::endl;
}

常引用保证了传递的数据不会被修改。


权限放大

//只读型(const)
const int a = 20;//可读可写型  报错!
int &b= a;      × × ×//权限平移
const int &c = a;   √ √ √ 

权限缩小

//可读可写型
int e = 30;//只读型
const int &f = e;     √ √ √

临时变量具有常属性

类型转换,并不会改变变量类型,中间都会产生一个临时变量!!
//临时变量具有常属性 --- 相当于被const修饰了
int ii = 1;
//发生 -- 隐式转换 -- 
double dd = ii;        //隐式类型转换是语法允许的--------------------------//报错   权限被放大
double &rdd = ii;      // × × × 权限被放大了
//权限的平移
const double &rdd = ii;

在这里插入图片描述


使用反例

void func1(int  n)
{}
void func2(int& n)
{}
void func3(const int& n)
{}int main()
{int a = 10;const int b = 20;func1(a);func1(b);func1(30);func2(a);//权限被放大   -- 报错 --func2(b);//权限被放大   -- 报错 --func2(30);double d = 2.22;//权限被放大   -- 报错 --func2(d);//语法允许func3(d);return 0;
}

总结

  • 可以引用一个const对象,但是必须用const引用。const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大

  • 权限放大和缩小只针对引用和指针

  • 不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样一些场景下a*3的和结果保存在一个临时对象中, int& rd = d 也是类似,在类型转换中会产生临时对象存储中间值,也就是时,rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里就触发了权限放大,必须要用常引用才可以。

  • 所谓临时对象就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象,C++中把这个未命名对象叫做临时对象。

3.4 引用与多态

在多态场景中,引用可以通过基类指向派生类,实现多态行为:

class Base {
public:virtual void show() { std::cout << "Base" << std::endl; }
};class Derived : public Base {
public:void show() override { std::cout << "Derived" << std::endl; }
};void display(Base &obj) {obj.show();  // 基类引用可指向派生类
}

4. C++ 引用的优缺点

优点

  • 语法简化,操作更加直观。
  • 避免空指针或野指针问题。
  • 减少拷贝,提高函数调用效率。

缺点

  • 必须在声明时初始化,灵活性不如指针。
  • 一旦初始化不能更改指向对象。
  • 使用不当时可能导致悬空引用。

5. 引用的注意事项与常见陷阱

  • 不要返回局部变量的引用:局部变量在函数结束后会被销毁,返回其引用会导致悬空引用。
  • 避免引用无效内存:确保引用指向合法的内存空间,避免运行时错误。
  • 引用与指针的混用:引用虽然简化了很多操作,但并不能完全替代指针,特别是在涉及动态内存管理时。

6. 总结

C++ 引用是简化代码、提高程序效率的重要工具,特别是在参数传递、返回值优化等场景中发挥了重要作用。与指针相比,引用更加简洁、安全,但在灵活性上有所限制。通过正确理解和使用引用,可以让你的 C++ 代码更加高效、稳健。

结语

希望这篇博客能帮助你深入理解 C++ 中的引用。祝你在编程的旅途中不断进步!如有任何问题或需要进一步讨论的内容,欢迎在评论区留言交流!

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。

也可以点点关注,避免以后找不到我哦!

Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!

在这里插入图片描述

参考:【C++】之引用详解 什么是引用?_c++引用-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/430773.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新品亮相|美格智能SLM530/SLM530P智能模组,助力金融新零售智慧升级

随着金融支付产业数字化与智能化不断推进&#xff0c;泛支付场景一体化解决方案成为行业发展的新趋势&#xff0c;从手持POS机到智能收款机&#xff0c;金融支付领域需要更快速、更精准、更安全的解决方案&#xff0c;加快推进数字化升级进程。 近期&#xff0c;美格智能正式发…

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-18

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-18 1. The Application of Large Language Models in Primary Healthcare Services and the Challenges W YAN, J HU, H ZENG, M LIU, W LIANG - Chinese General Practice, 2024 人工智能大语言模型在基层医疗…

基于深度学习的文本情感原因提取研究综述——论文阅读

前言 既然要学习情感分析&#xff0c;那么肯定还要了解情感原因对抽取的发展历程&#xff0c;所以我又搜了一篇研究综述&#xff0c;虽然是2023年发表的&#xff0c;但是里面提及到的历程仅停留到2022年。这篇综述发布在TASLP期刊&#xff0c;是音频、声学、语言信号处理的顶级…

静态路由和默认路由(实验)

目录 一、实验设备和环境 1、实验设备 2、实验环境 &#xff08;1&#xff09;实验拓扑图 &#xff08;2&#xff09;实验命令列表 二、实验记录 1、直连路由与路由表查看 步骤1:建立物理连接并运行超级终端。 步骤2:在路由器上查看路由表。 2、静态路由配置 步骤1:配…

哈希表与离散化

一、字符串哈希 1. 什么是哈希 哈希算法是&#xff1a;通过哈希函数将字符串、较大的数等转换为能够用变量表示的或者是直接作为数组下标的数&#xff0c;通过哈希算法转换到的值&#xff0c;称之为哈希值。哈希值可以实现快速查找和匹配。 比如&#xff1a;用数组下标计数法&…

QT widgets 窗口缩放,自适应窗口大小进行布局

1. 窗口布局 2. 尺寸策略&#xff1a;扩展 Fixed (固定): 行为&#xff1a;控件的大小是固定的&#xff0c;不会随着窗口大小的变化而改变。它的大小由控件的 sizeHint() 返回的值决定。 适用场景&#xff1a;当你希望控件的大小保持不变&#xff0c;不随布局调整时使用&#x…

Windows下利用MSYS2和VS的nmake编译nginx源码

目录 一、使用说明 二、安装软件 2.1 下载依赖库 2.3 下载并安装 StrawberryPerl 2.4 下载并安装 MSYS 2 2.5 nginx源代码下载 三、编译配置 3.1 设置NGX_MSVC_VER 3.2 配置 Makefile 3.3 编译代码 3.4 整理Nginx发布环境 四、错误处理 一、使用说明 本文章主要记…

spring boot启动报错:so that it conforms to the canonical names requirements

springboot 2.x的版本中对配置文件中的命名规范有了强制性的要求&#xff0c;如下图所示中的dataSource属性属于驼峰格式&#xff0c;但是在springboot 2.x中不允许使用驼峰形式。 根据错误提示可知将其使用 - 来分割即可 错误信息的含义&#xff1a;“Canonical names should…

MySQL的msi版本9.0在安装过程总结和需要注意的地方

下载 参考文档 [官方包快速下载]&#xff08;https://dev.mysql.com/downloads/mysql/&#xff09; 使用zip文件安装可参考&#xff0c;这种直接把zip安装包解压到想要放的地方&#xff0c;并安装其中的方式一步步修改数据地址等配置即可。 个人使用了msi的安装文件 msi版本…

Kafka 3.0.0集群部署教程

1、集群规划 主机名 ip地址 node.id process.roles kafka1 192.168.0.29 1 broker,controller Kafka2 192.168.0.30 2 broker,controller Kafka3 192.168.0.31 3 broker,controller 2、将kafka包上传以上节点/app目录下 mkdir /app 3、解压kafka包 所有节点 …

JavaWeb--纯小白笔记06:使用Idea创建Web项目,Servlet生命周期,注解,中文乱码解决

使用Idea创建一个web项目----详细步骤配置&#xff0c;传送门&#xff1a;http://t.csdnimg.cn/RsOs7 src&#xff1a;放class文件 web&#xff1a;放html文件 out&#xff1a;运行过后产生的文件 一创建一个新的web项目(配置好了后)&#xff1a; 在src创建一个文件…

NVIDIA发布端到端自动驾驶框架Hydra-MDP

自动驾驶是目前人工智能领域的一个主要分支&#xff0c;目前特斯拉的FSD确实是为数不多的大模型框架。与其说特斯拉是一个造车公司&#xff0c;不如说是一个人工智能大数据公司。特斯拉每天靠行驶在道路上的汽车搜集的道路数据不胜其数&#xff0c;而拥有海量的数据是人工智能领…

001.从0开始实现线性回归(pytorch)

000动手从0实现线性回归 0. 背景介绍 我们构造一个简单的人工训练数据集&#xff0c;它可以使我们能够直观比较学到的参数和真实的模型参数的区别。 设训练数据集样本数为1000&#xff0c;输入个数&#xff08;特征数&#xff09;为2。给定随机生成的批量样本特征 X∈R10002 …

第十四届蓝桥杯嵌入式国赛

一. 前言 本篇博客主要讲述十四届蓝桥杯嵌入式的国赛题目&#xff0c;包括STM32CubeMx的相关配置以及相关功能实现代码以及我在做题过程中所遇到的一些问题和总结收获。如果有兴趣的伙伴还可以去做做其它届的真题&#xff0c;可去 蓝桥云课 上搜索历届真题即可。 二. 题目概述 …

论文阅读与分析:Few-Shot Graph Learning for Molecular Property Prediction

论文阅读与分析&#xff1a;Few-Shot Graph Learning for Molecular Property Prediction 论文地址和代码地址1 摘要2 主要贡献3 基础知识Meta Learning1 介绍2 学习算法Step 1: What is learnable in a learning algorithm?Step 2&#xff1a;Define loss function for learn…

基于C语言开发(控制台)通讯录管理程序

通讯录程序设计 一、课程设计题目与要求 题目 &#xff1a;通讯录管理程序 1. 问题描述 编写一个简单的通讯录管理程序。通讯录记录有姓名&#xff0c;地址(省、市(县)、街道)&#xff0c;电话号码&#xff0c;邮政编码等四项。2. 基本要求 程序应提供的基本基本管理功能有…

众数信科AI智能体政务服务解决方案——寻知智能笔录系统

政务服务解决方案 寻知智能笔录方案 融合民警口供录入与笔录生成需求 2分钟内生成笔录并提醒错漏 助办案人员二次询问 提升笔录质量和效率 寻知智能笔录系统 众数信科AI智能体 产品亮点 分析、理解行业知识和校验规则 AI实时提醒用户文书需注意部分 全文校验格式、内…

领域驱动DDD三种架构-分层架构、洋葱架构、六边形架构

博主介绍&#xff1a; 大家好&#xff0c;我是Yuperman&#xff0c;互联网宇宙厂经验&#xff0c;17年医疗健康行业的码拉松奔跑者&#xff0c;曾担任技术专家、架构师、研发总监负责和主导多个应用架构。 技术范围&#xff1a; 目前专注java体系&#xff0c;以及golang、.Net、…

(1999-2018年)全国各城市-财政收入–营业税

涵盖了1999年至2018年间&#xff0c;全国各城市的财政收入中营业税的部分。数据来源于中国区域统计年鉴及各省市统计年鉴 1999-2018年全国各城市-财政收入-营业税资源-CSDN文库https://download.csdn.net/download/2401_84585615/89504622 不同行业对营业税的贡献也存在差异。…

电动车车牌识别系统源码分享

电动车车牌识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…