【C++指南】深入剖析:C++中的引用

           💓 博客主页:倔强的石头的CSDN主页 

           📝Gitee主页:倔强的石头的gitee主页

            ⏩ 文章专栏:《C++指南》

                                  期待您的关注

 

1b7335aca73b41609b7f05d1d366f476.gif

目录

引言:

 一、引用的基本概念

1. 定义与特性

2. 语法与声明

二、引用的进阶用法

1. 函数参数传递

2. 返回值优化

3. 引用与指针的比较

三、引用的实战应用

1.案例分析

2.性能优化

3.最佳实践

四、const引用

结尾总结


 

 

引言

引用在C++中扮演着重要的角色。它允许我们为已存在的变量创建一个别名,通过这个别名,我们可以直接访问和操作原始变量。这一特性不仅简化了代码,提高了代码的可读性,还带来了性能上的优势。因为引用本身不是一种数据类型,不占用存储单元,所以使用引用可以减少数据的复制,降低内存占用,提高程序的执行效率。

然而,尽管引用在C++编程中如此重要,但初学者往往对其感到困惑。他们可能不清楚何时使用引用,如何正确地使用引用,以及引用与指针之间的区别和联系。因此,深入学习和理解C++中的引用变得尤为重要。

本文旨在深入探讨C++中的引用,从基本概念到高级用法,再到实战应用,全面剖析引用的各个方面。希望通过本文的学习,读者能够掌握引用的核心概念,理解其工作机制,学会在实际编程中灵活运用引用,编写出更高效、更简洁的代码。同时,本文也将提供一些最佳实践和常见误区的指导,帮助读者避免在使用引用时犯错,进一步提高编程水平。

 

 一、引用的基本概念

在C++中,引用(Reference)是一种特殊的变量类型,它为已存在的变量提供了一个别名。引用本身并不占据独立的内存空间,而是与它所引用的变量共享同一块内存地址。

以下是对C++引用基本概念的详细阐述:

1. 定义与特性

  • 定义:引用是C++中对某一变量(目标变量)的别名。通过引用,我们可以直接访问和操作原始变量,而无需通过指针的间接访问方式。
  • 特性(重要)
    • 别名关系:引用一旦与某个变量关联起来,就始终指向该变量,成为其别名。对引用的操作实际上就是对原始变量的操作。
    • 必须初始化:引用在声明时必须被初始化,且一旦初始化后,其引用的对象不能改变。即引用不能重新绑定到另一个变量上。
    • 不占内存:从概念上讲,引用本身不占用内存空间,因为它只是原始变量的一个别名。但在底层实现上,编译器通常会将引用实现为指向原始变量的常量指针(const pointer),因此实际上会占用指针大小的内存。
    • 类型一致:引用的类型必须与它所引用的变量的类型一致。这是因为引用本质上是对原始变量的一种直接访问方式,类型不一致会导致访问和操作上的混乱。

2. 语法与声明

  • 声明方式:在C++中,使用&符号来声明引用。引用的符号与取地址符号相同,这是通过运算符重载实现的,会在后面发布的文章中详细介绍
  • 其基本语法如下:
    类型标识符& 引用名 = 已存在的变量名;
    #include<iostream>
    using namespace std;
    int main()
    {
    	int a = 0;
    	// 引⽤:b和c是a的别名
    
    	int& b = a;
    	int& c = a;
    	// 也可以给别名b取别名,d相当于还是a的别名
    
    	int& d = b;
    	++d;
    	// 这⾥取地址我们看到是⼀样的
    
    	cout << &a << endl;
    	cout << &b << endl;
    	cout << &c << endl;
    	cout << &d << endl;
    	return 0;
    }

    d5fc1456e2a245b5a7a180b968a77bdd.png

 

二、引用的进阶用法

在C++编程中,引用不仅用于基本的变量别名,还广泛应用于函数参数传递、返回值优化等高级用法。甚至可以说引用的实际使用中,主要还是用于参数传递和返回值接收。

以下是对这些高级用法的详细阐述:

 

1. 函数参数传递

通过引用传递函数参数是C++中常用的一种优化手段。

与传统的值传递相比,引用传递可以避免数据的复制,从而提高函数的执行效率。特别是在传递大型对象或结构体时,引用传递的优势更加明显。它允许函数直接访问和修改原始数据,而无需进行数据的复制和回传。

示例

void swap(int& x, int& y) {
	int temp = x;
	x = y;
	y = temp;
}

在这个示例中,swap函数通过引用传递了两个整数参数xy。在函数内部,它交换了这两个整数的值。由于使用了引用传递,所以交换操作直接作用于原始变量上,无需进行数据的复制。

 

2. 返回值优化

当函数需要返回一个大对象或类的实例时,通过返回引用可以避免对象的复制,从而提高效率。这种优化手段特别适用于返回大型数据结构或类实例的情况。然而,需要注意的是,返回局部对象的引用是危险的,因为局部对象在函数返回后会被销毁,返回的引用将指向一个无效的内存地址。

示例

const MyClass& getMyClassInstance() 
{ 
    static MyClass instance; 
    return instance; 
}

 

在这个示例中,getMyClassInstance函数返回了一个MyClass类型的对象的引用。由于返回的是静态局部对象的引用,所以该对象在函数调用结束后仍然存在,返回的引用是有效的。

 

3. 引用与指针的比较

引用和指针在C++中都是用于间接访问数据的工具,但它们在使用上有一些重要的区别。

  • 安全性引用在使用时更加安全。因为引用必须被初始化,且不能为空,所以它可以保证始终指向一个有效的内存地址。相比之下,指针可以为空,也可以指向任意内存地址,这增加了使用指针时的风险。
  • 简洁性引用在语法上更加简洁。使用引用时,无需进行解引用操作,代码更加易读和易写。而指针则需要进行解引用操作才能访问其指向的数据。
  • 灵活性指针则更加灵活。指针可以进行算术运算和指针运算,这使得指针在处理数组和动态内存分配时更加有用。而引用则不支持这些操作。

引用和指针在C++中各有其优势和用途。在选择使用引用还是指针时,需要根据具体的编程需求和上下文环境来做出决策。

 

三、引用的实战应用

在C++编程实践中,引用发挥着举足轻重的作用。以下通过几个案例分析,探讨引用的实战应用,并给出最佳实践建议。

1.案例分析

交换函数

交换函数是一个典型的引用应用案例。通过使用引用传递参数,我们可以轻松实现两个变量的交换,而无需进行数据的复制

void swap(int& x, int& y) {
	int temp = x;
	x = y;
	y = temp;
}

在这个例子中,swap函数接收两个整数的引用作为参数,并通过一个简单的中间变量来交换它们的值。由于使用了引用,所以交换操作直接作用于原始变量上,效率非常高。

 

链表操作

在链表操作中,引用也经常被用来传递节点指针,以避免节点的复制。例如,在插入或删除链表节点时,我们可以通过引用直接修改链表的结构,而无需复制节点数据。

void insert(ListNode*& head, int value) 
{ 
    ListNode* newNode = new ListNode(value); 
    newNode->next = head; 
    head = newNode; 
}

在这个例子中,insert函数接收一个指向链表头节点的引用的指针,并插入一个新的节点。由于使用了引用,所以函数能够直接修改头节点的值,而无需返回新的头节点。

 

2.性能优化

通过使用引用,我们可以显著减少数据的复制,从而降低内存占用并提高执行速度。在大型项目中,合理使用引用可以带来显著的性能提升。

例如,在传递大型对象或类的实例时,通过返回引用可以避免对象的复制。同样地,在函数参数传递时,使用引用也可以避免数据的复制,从而提高函数的执行效率。

 

3.最佳实践

  1. 函数参数传递和返回值:在可能的情况下,优先考虑使用引用。这可以避免数据的复制,提高函数的执行效率。

  2. 避免将引用作为函数的输出参数:虽然引用可以作为函数的输出参数,但这可能会降低代码的可读性。更好的做法是使用函数的返回值来传递输出结果。

  3. 注意引用的有效性:在使用引用时,要确保引用的变量在引用期间是有效的。避免引用已经销毁的变量,这可能会导致未定义的行为或程序崩溃。

 

通过合理使用引用,我们可以提高代码的执行效率、降低内存占用,并编写出更加简洁易读的代码。在实践中,我们应该充分利用引用的优势,并注意避免潜在的陷阱和错误。

 

四、const引用

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

 

不过需要注意的是类似

int& rb = a*3;

double d = 12.34;

int& rd = d;

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

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

 

应用实例:

int main()
{
 const int a = 10;
 // 编译报错:error C2440: “初始化”: ⽆法从“const int”转换为“int &”
 // 这⾥的引⽤是对a访问权限的放⼤

 //int& ra = a;
 // 这样才可以

 const int& ra = a;
 // 编译报错:error C3892: “ra”: 不能给常量赋值

 //ra++;
 // 这⾥的引⽤是对b访问权限的缩⼩

 int b = 20;
 const int& rb = b;
 // 编译报错:error C3892: “rb”: 不能给常量赋值

 //rb++;
 return 0;
}

 

结尾总结

引用,作为C++编程中的一项核心特性,其重要性不言而喻。引用不仅使代码更加简洁、易读,还通过减少数据复制,显著提升了程序的执行效率,降低了内存占用。通过案例分析,我们深刻体会到引用在交换函数、链表操作等场景中的实战应用,它使我们能够直接访问和修改原始数据,而无需繁琐的数据复制过程。

同时,我们也明确了在使用引用时需要遵循的最佳实践。在函数参数传递和返回值时,应优先考虑使用引用,以提高效率。然而,我们也应警惕将引用作为函数的输出参数,因为这可能会降低代码的可读性。更重要的是,我们必须时刻注意引用的有效性,确保引用的变量在引用期间始终有效,以避免未定义的行为或程序崩溃。

综上所述,引用是C++编程中不可或缺的一部分。它为我们提供了强大的工具,使我们能够编写出更加高效、简洁、易读的代码。在未来的编程实践中,我们应该充分利用引用的优势,并注意遵循最佳实践,以确保代码的质量和稳定性。

 

 

 

本文完

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[HNCTF 2022 WEEK2]getflag-入土为安的二十一天

难点读程序&#xff0c;写exp *(unsigned __int8 *)(i a1) >> 4: 这将字节 i a1 右移 4 位&#xff0c;提取出字节的高 4 位。 *(_BYTE *)(i a1): 这获取原字节的低 4 位&#xff08;即&#xff0c;i a1 位置的字节的低 4 位&#xff09;。 (16 * *(_BYTE *)(i a1))…

怎么在网络攻击中屹立不倒

在当今蓬勃发展的网络游戏产业中&#xff0c;服务器安全无疑是企业生存与发展的基石。面对互联网环境中无处不在的DDoS&#xff08;分布式拒绝服务&#xff09;与CC&#xff08;挑战碰撞&#xff09;攻击威胁&#xff0c;游戏服务器的防御能力与高效处理能力显得尤为重要。相较…

EmguCV学习笔记 VB.Net 2.S 特别示例

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 教程VB.net版本请访问&#xff1a;EmguCV学习笔记 VB.Net 目录-CSDN博客 教程C#版本请访问&#xff1a;EmguCV学习笔记 C# 目录-CSD…

ffmpeg的基础命令

文章目录 ffmpeg/ffplay/ffprobe区别ffmpeg 的作用ffplay的作用ffprobe的作用 ffmpeg使用概述功能概述转码过程简单使用FFMPEG -i常用的 -i例子 ff***工具之间共享的选项ffmpeg主要选项ffmpeg提取音视频数据ffmpeg命令修改原有的视频格式ffmpeg命令裁剪和合并视频拼接视频的方式…

计算机网络基础详解:从网络概述到安全保障的全面指南

目录 网络基础详细概述 1. 网络概述 1.1数据通信 1.2资源共享 1.3分布式处理 1.4负载均衡 2. 网络分类 2.1按覆盖范围&#xff1a; 2.1.1局域网 (LAN)&#xff1a; 2.1.2城域网 (MAN)&#xff1a; 2.1.3广域网 (WAN)&#xff1a; 2.2按拓扑结构&#xff1a; 2.2.1…

python request 发送包含文件请求

file_path rD:\work\200K.pdf # 额外的参数 # 请求文件 url "http://192.168.1.111:8888/test"payload {param1: test,param2: test2} files [(file, (file_path, open(file_path, rb), application/pdf)) ] headers {} response requests.request("POST&…

X-Recon:一款针对Web安全的XSS安全扫描检测工具

关于X-Recon X-Recon是一款功能强大的Web安全扫描与检测工具&#xff0c;该工具能够帮助广大研究人员识别网页端输入数据&#xff0c;并执行XSS扫描任务。 功能介绍 1、子域名发现&#xff1a;检索目标网站的相关子域名并将其整合到白名单中。这些子域名可在抓取过程中使用&am…

yolov8旋转框+关键点检测

一、Yolov8obb_kpt -----------------------------------现已在v8官方库上更新旋转框分割算法和旋转框关键点检测算法-------------------------- ------------------------------------------- https://github.com/yzqxy/ultralytics-obb_segment---------------------------…

苗情灾情监控系统的工作原理

TH-MQ1苗情灾情监控系统&#xff0c;也常被称为作物生长检测仪&#xff0c;是现代农业技术中的一项重要创新&#xff0c;它集成了物联网、大数据、人工智能等先进技术&#xff0c;为农业生产提供了全面、精准的监测与诊断服务。通过集成高清摄像头、高精度传感器、无人机等多种…

【TCP/IP】自定义应用层协议,常见端口号

互联网中&#xff0c;主流的是 TCP/IP 五层协议 5G/4G 上网&#xff0c;是有自己的协议栈&#xff0c;要比 TCP/IP 更复杂&#xff08;能够把 TCP/IP 的一部分内容给包含进去了&#xff09; 应用层 可以代表我们所编写的应用程序&#xff0c;只要应用程序里面用到了网络通信…

VueX 使用

1.简介 就是用来多组件共享数据的实现用的 2.使用VueX 因为使用的是vue2 所以下的是vuex3 若是vue3 必须下的是 vue4 npm i vuex3 3.搭建环境 1.创建 src/store/index.js //该文件用于创建一个Vuex中最为核心的store//引入VueX import Vuex from vuex import Vue from vu…

微服务系列:Spring Cloud 之 Feign、Ribbon、Hystrix 三者超时时间配置

Feign 自身有超时时间配置 Feign 默认集成的 Ribbon 中也有超时时间配置 假如我们又使用了 Hystrix 来实现熔断降级&#xff0c;Hystrix 自身也有一个超时时间配置 注: spring-cloud-starter-openfeign 低一点的版本中默认集成的有 Hystrix&#xff0c;高版本中又移除了。 …

XSS-DOM

文章目录 源码SVG标签Dom-Clobbringtostring 源码 <script>const data decodeURIComponent(location.hash.substr(1));;const root document.createElement(div);root.innerHTML data;// 这里模拟了XSS过滤的过程&#xff0c;方法是移除所有属性&#xff0c;sanitize…

如何发布自己的NPM包详细步骤

前言 在前端开发中&#xff0c;将自己编写的 Vue 组件或插件打包并发布到 NPM 上&#xff0c;不仅可以方便自己在其他项目中复用&#xff0c;还能分享给更多的开发者使用。本文将从 NPM 注册、登录与发布流程&#xff0c;及如何通过 Vue CLI 打包插件的角度详细介绍如何发布 V…

【Linux-进程】系统初识:冯诺依曼体系结构

系列文章&#xff1a;《Linux入门》 目录 冯诺依曼体系结构 1&#xff09;硬件上 &#x1f337;1.什么是冯诺依曼体系结构&#xff1f; &#x1f337;2.冯诺依曼结构的五个主要组成部分 1.运算器 2.控制器 3.存储器 4.输入输出 设备 ⁉️3.为什么还需要内存呢&#xf…

vue中点击导航栏,动态改变样式,经典写法

vue中点击导航栏&#xff0c;动态改变样式&#xff0c;经典写法 在vue中&#xff0c;我们通常会有这样的情况&#xff0c;在多个子模块之间&#xff0c;点击其中一个子模块&#xff0c;修改当前点击的子模块的样式。如图&#xff0c;点击B模块时&#xff0c;模块B样式改变&…

小卷原创视频教程:Java开发必会的Linus环境搭建

csdn的各位同学&#xff0c;大家好&#xff0c;我是小卷。最近一段时间写博客不是那么勤快了&#xff0c;主要是在帮助Java小白做学习录屏。 后续更多会以学习视频的方式和大家一起交流Java、前端以及相关的技术。本次分享的是Java开发必须要会的Linux环境搭建。 衷心感谢各位小…

登录过程记录

过程&#xff1a; 未登录状态打开我的消息页-》调用后端接口查询登录状态->后端接口从cookie里拿lt,判断是否登录-》未登录&#xff0c;携带页面链接(我的消息)跳转passport【单点登录服务】 登录页-》输入验证码提交后-》验证成功-》根据用户信息生成票据-》携带票据和我的…

电动汽车和混动汽车DC-DC转换器的创新设计与测试方法

汽车 DC-DC 转换器市场规模将达到187亿美元&#xff0c;年复合增长率为10%。 DC-DC 转换器是汽车的重要组成部分&#xff0c;它可以通过电压转换为各种车载系统供电&#xff0c;例如日益复杂的车载信息娱乐系统、使用驾驶辅助系统&#xff08;ADAS&#xff09;实现的增强安全功…

C++复习之STL

STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是C标准库的一部分&#xff0c;提供了丰富且高效的数据结构和算法。STL主要由6大组件构成&#xff0c;分别是容器、算法、迭代器、适配器、仿函数和空间配置器。 容器&#xff08;Containers&#…