当前位置: 首页 > news >正文

【c++】深入理解别名机制--引用

🌟🌟作者主页:ephemerals__

🌟🌟所属专栏:C++

目录

前言

一、引用的概念和定义

二、引用的特性

三、引用的实用性

1.引用传参

2.引用做返回值

2.1 引用做返回值的作用

2.2 引用坍缩问题、悬挂引用问题

四、const修饰引用

五、引用和指针的联系

总结


前言

        我们都知道,在c语言中,指针是一种功能十分强大的数据类型,它允许我们直接访问并且操作内存。然而,它在使用时稍有不慎,就会出错。对此,c++引入了一个新的概念:引用。引用可以实现部分类似于指针的功能,并且它比指针更加安全、简洁。

一、引用的概念和定义

        引用,作为c++中的一种特殊别名机制,当我们定义引用时,并不是创建了一个新变量,而是

给原有的变量起了一个别名。它的定义方式如下:

(数据类型)& 引用名 = 引用对象;

代码举例:

#include <iostream>
using namespace std;int main()
{int a = 0;int& b = a;//定义引用,给a取了一个别名a++;cout << b << endl;b++;cout << a << endl;return 0;
}

运行结果:

可以看到,无论是对a自增,还是对b自增,它们表示的值都会发生改变。我们再来打印一下它们的地址:

cout << &a << endl;
cout << &b << endl;

结果显示它们的地址是相同的。这表明引用只是给变量起了一个别名,表示的还是同一块内存空间

我们画图表示一下引用:

二、引用的特性

        引用有以下三点语法特性:

1.引用在定义的时候必须要表明它所表示的对象。

2.由于引用是用作给变量取别名,所以一个变量可以有多个引用。当然,引用也可以有引用。

3.引用一旦指定了对象,就不能再指定其他对象

三、引用的实用性

        了解的引用的概念和特性之后,我们不禁会发出疑问:既然要对变量进行操作,直接修改不就好了嘛,何必还要取一个别名呢?

1.引用传参

        举一个例子:

#include <iostream>
using namespace std;void Swap(int& x, int& y)
{int tmp = x;x = y;y = tmp;
}int main()
{int a = 3;int b = 5;Swap(a, b);//交换a和b的值cout << "a = " << a << endl;cout << "b = " << b << endl;return 0;
}

运行结果:

可以看到,使用引用传参,通过函数交换了变量a和b的值。由于引用是给变量起别名,所以此时的x和y就表示a和b本身。因此,我们在函数内部就实现了这两个元素的交换。相比传址调用,它的写法更加简单,并且在语法层面,引用是不开辟新内存的,减少了拷贝,节省了内存空间。

2.引用做返回值

2.1 引用做返回值的作用

        首先来看一段代码:

#include <iostream>
using namespace std;int fun()
{static int a = 10;return a;
}int main()
{fun()++;//报错cout << fun() << endl;return 0;
}

很显然,以上代码是不可行的。函数的返回值是一个临时变量,而临时变量具有常性,我们无法对这个值进行修改。但是引用做返回值可以做到这一点:

#include <iostream>
using namespace std;int& fun()
{static int a = 10;return a;
}int main()
{fun()++;cout << fun() << endl;return 0;
}

我们将返回值改成int的引用类型,则此时函数返回静态变量a的别名,所以我们让它自增,就相当于改变了a的值。

        有了引用做返回值,我们在调用函数的时候就可以通过这个返回值直接访问和修改原始对象,并且避免了临时变量的拷贝,增加程序运行的效率。

2.2 引用坍缩问题、悬挂引用问题

        刚才引用做返回值的方法虽然好用,但是难免会出现一些问题。举个例子:

#include <iostream>
using namespace std;int& func1()
{static int a = 0;return a;
}int main()
{int x = func();return 0;
}

虽然这里的func1函数返回了a的引用,但是我们却在主函数中以一个整形变量来接收,这里就会发生一种隐式的类型转换--引用坍缩,编译器会将这个返回值转换为它所引用的对象的一个临时拷贝这将导致我们无法访问并修改a的值,达不到预期效果。所以一定要以相同类型的引用来接收引用返回值

        再举一个例子:

#include <iostream>
using namespace std;int& func2()
{int a = 0;return a;
}int main()
{int& x = func();return 0;
}

在func2函数中,我们创建了一个局部变量a并且返回它的引用,但是由于a是一个局部变量,当函数栈帧销毁时,变量a的空间已经被释放了,此时的返回值就变成一个悬挂引用(野引用),也就是说这个引用的主体已经不存在了,程序的运行结果就是未定义的。所以我们在使用引用做返回值时,一定要注意返回后的引用主体是否还存在

四、const修饰引用

        我们在定义引用时,可以在变量名之前加上const修饰(称之为常引用)。当一个引用被const修饰时,该引用就无法修改其所表示的对象。例如:

#include <iostream>
using namespace std;int main()
{int a = 0;const int& b = a;a = 10;b = 20;//报错return 0;
}

注意:对于一个被const修饰的变量,定义它的引用时也需要用const修饰。例如:

#include <iostream>
using namespace std;int main()
{const int a = 0;int& b = a;//报错const int& c = a;//正确return 0;
}

对于以下情况,定义引用时也必须要用const修饰:

#include <iostream>
using namespace std;int main()
{int a = 5;const int& b = a * 3;//a*3是一个临时对象,具有常性,它的引用要用const修饰float c = 5.5f;const int& d = c;//当引用和对象的类型不同时,由于隐式类型转换的结果是一个临时对象,定义引用也需要用const修饰return 0;
}

五、引用和指针的联系

        引用和指针是相辅相成的,它们能够实现对方的部分功能,但是又不可完全替代。它们的一些联系和区别如下:

1.从语法层面上,引用是对一个对象取别名,不会开辟空间;而指针用于存储一个对象的地址,会开辟空间。

2.定义引用时,必须要指定表示的对象;而指针在定义时可以不指向对象。

3.引用不能改变表示的对象,而指针可以改变。

4.由于引用是对象的别名,所以可以直接通过引用访问对象;而指针则需要解引用才能访问对象。

5.相比指针,引用在使用上更加安全,不容易出现悬挂引用的问题。

6.在某些情况下,指针和引用在语义上可以相互替代,例如函数传参,都可以形成数据共享,并且避免内存的过度消耗。

总结

        今天,我们学习了引用。引用的功能十分强大,同时也弥补了指针的一些不足。深入理解引用对我们之后学习并实现类的相关功能有很大帮助。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

相关文章:

【c++】深入理解别名机制--引用

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 一、引用的概念和定义 二、引用的特性 三、引用的实用性 1.引用传参 2.引用做返回值 2.1 引用做返回值的作用 2.2 引用坍缩问题、悬挂引用问…...

简便的qemu img扩容方法

虚拟机用着用着磁盘空间就不够了&#xff0c;那就要想办法增加磁盘空间大小 了。在虚拟机本身磁盘的基础上直接增加空间大小最简便&#xff0c;于是记录一下方法。 首先&#xff0c;在虚拟机关机状态下&#xff0c;使用qemu-img命令给虚拟机的磁盘镜像增加虚拟空间5GB&#xff…...

EPERM: operation not permitted,

这个错误提示 EPERM: operation not permitted, mkdir C:\Program Files\nodejs\node_global\node_modules\pnpm_tmp 通常是因为权限不足导致的。在 Windows 系统中&#xff0c;C:\Program Files\ 目录通常需要管理员权限才能写入。 要解决这个问题&#xff0c;你可以尝试以下…...

将Centos 8 Linux内核版本升级或降级到指定版本

本文以centos 8.0为例&#xff0c;内核版本为4.18.0-80.el8.x86_64&#xff0c;升级到内核版本为4.18.0-80.4.2.el8_0.x86_64。 1.查看当前系统版本信息 [rootcentos80-1905 ~]# uname -sr Linux 4.18.0-80.el8.x86_642.在网站&#xff1a;https://vault.centos.org/里面下载…...

小程序商城被盗刷,使用SCDN安全加速有用吗?

在电子商务蓬勃发展的今天&#xff0c;小程序商城因其便捷性和灵活性成为商家和消费者的新宠。然而&#xff0c;随着其普及&#xff0c;小程序商城的安全问题也日益凸显&#xff0c;尤其是盗刷现象频发&#xff0c;给商家和用户带来了巨大损失。面对这一挑战&#xff0c;是否可…...

nginx的基本使用与其日志

文章目录 1.nginx编译安装脚本2.nginx平滑升级&#xff0c;以及其步骤3.nginx核心配置&#xff0c;及实现nginx多虚拟主机4.nginx日志格式定制5.nginx反向代理及https安全加密6.基于LNMP和Redis的phpmyadmin的会话保持&#xff0c;以及其完整步骤 1.nginx编译安装脚本 #编译安…...

linux | 苹果OpenCL(提高应用软件如游戏、娱乐以及科研和医疗软件的运行速度和响应)

点击上方"蓝字"关注我们 01、引言 >>> OpenCL 1.0 于 2008 年 11 月发布。 OpenCL 是为个人电脑、服务器、移动设备以及嵌入式设备的多核系统提供并行编程开发的底层 API。OpenCL 的编程语言类似于 C 语言。其可以用于包含 CPU、GPU 以及来自主流制造商如 …...

算法-UKF中Sigma点生成

void UKF::MakeSigmaPoints() {Eigen::VectorXd x_aug_ Eigen::VectorXd(n_x_);x_aug_.head(n_x_) x_;Eigen::MatrixXd P_aug Eigen::MatrixXd::Zero(n_x_, n_x_);// 转成正定矩阵P_aug pdefinite_svd(P_);// LLT分解Eigen::MatrixXd L P_aug.llt().matrixL();sigma_point…...

精选五款热门骨传导耳机分享,让你避免踩坑的陷阱

因为骨传导耳机独特的佩戴方式和声音的传播方式&#xff0c;受到了小耳、油耳以及运动爱好者的的喜爱&#xff0c;但也由于市面上的骨传导耳机品牌越来越多&#xff0c;很多朋友不知道该怎么选择&#xff0c;今天我挑选出市面上体验感较好&#xff0c;各方面比较出色的骨传导给…...

「字符串」前缀函数|KMP匹配:规范化next数组 / LeetCode 28(C++)

概述 为什么大家总觉得KMP难&#xff1f;难的根本就不是这个算法本身。 在互联网上你可以见到八十种KMP算法的next数组定义和模式串回滚策略&#xff0c;把一切都懂得特别混乱。很多时候初学者的难点根本不在于这个算法本身&#xff0c;而是它令人痛苦的百花齐放的定义。 有…...

python人工智能002:jupyter基本使用

小知识&#xff1a;将jupyter修改为中文&#xff0c;修改用户变量&#xff0c; 注意是用户变量&#xff0c;不是系统变量 新增用户变量 变量名&#xff1a;LANG 变量值&#xff1a;zh_CN.UTF8 然后重启jupyter 上一章的软件安装完成之后&#xff0c;就可以创建文件夹来学习写…...

Linux使用 firewalld管理防火墙命令

Linux 发行版中使用的动态防火墙管理工具。使用 firewalld&#xff0c;你可以查看防火墙状态、当前配置的规则以及开放的端口。以下是一些常用的 firewalld 命令来管理和查看防火墙状态及端口配置。 1. 查看防火墙状态 检查 firewalld 是否正在运行 sudo systemctl status f…...

二叉树(三)

一、二叉树的遍历 二叉树遍历是按照某种特定的规则&#xff0c;依次对二叉树中的结点进行相应的操作&#xff0c;并且每个结点只操作一次。 1.前序遍历&#xff08;先根遍历&#xff09; 前序遍历&#xff08;Preorder Traversal也叫先序遍历&#xff09;——根、左子树、右…...

05--kubernetes组件与安装

前言&#xff1a;终于写到kubernetes&#xff08;k8s&#xff09;&#xff0c;容器编排工具不止k8s一个&#xff0c;它的优势在于搭建集群&#xff0c;也是传统运维和云计算运维的第一道门槛&#xff0c;这里会列出两种安装方式&#xff0c;详细步骤会在下文列出&#xff0c;文…...

EmguCV学习笔记 VB.Net和C# 下的OpenCv开发 C# 目录

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…...

探索TensorFlow:深度学习的未来

标题&#xff1a;探索TensorFlow&#xff1a;深度学习的未来 在当今快速发展的人工智能领域&#xff0c;TensorFlow无疑是最耀眼的明珠之一。TensorFlow是由Google Brain团队开发的一个开源机器学习框架&#xff0c;它以其强大的灵活性、易用性和高效的性能&#xff0c;迅速成…...

探索地理空间分析的新世界:Geopandas的魔力

文章目录 探索地理空间分析的新世界&#xff1a;Geopandas的魔力背景&#xff1a;为何选择Geopandas&#xff1f;这个库是什么&#xff1f;如何安装这个库&#xff1f;五个简单的库函数使用方法场景应用&#xff1a;Geopandas在实际工作中的应用常见bug及解决方案总结 探索地理…...

如何为网站申请免费SSL证书?

一、准备阶段 确定证书类型&#xff1a; 对于大多数个人博客和小型企业网站&#xff0c;DV&#xff08;域名验证&#xff09;SSL证书已足够使用&#xff0c;因为它仅验证域名所有权&#xff0c;成本较低且验证快速。准备域名&#xff1a; 确保你拥有一个有效的域名&#xff0c…...

Java项目集成RocketMQ

文章目录 1.调整MQ的配置1.进入bin目录2.关闭broker和namesrv3.查看进程确认关闭4.编辑配置文件broker.conf&#xff0c;配置brokerIP15.开放端口109116.重新启动1.进入bin目录2.启动mqnamesrv和mqbroker1.启动 NameServer 并将输出重定向到 mqnamesrv.log2.**启动 Broker 并将…...

如何将 Bamboo agent 能力迁移到极狐GitLab tag 上?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...