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

【C++初阶(三)引用与内联函数】

本专栏内容为:C++学习专栏,分为初阶和进阶两部分。 通过本专栏的深入学习,你可以了解并掌握C++。

💓博主csdn个人主页:小小unicorn
⏩专栏分类:C++
🚚代码仓库:小小unicorn的代码仓库🚚
🌹🌹🌹关注我带你学习编程知识

C++初阶(三)

  • 引用
    • 概念
    • 引用的特性
      • 一、引用在定义时必须初始化
      • 二、一个变量可以有多个引用(多个别名)
      • 三、引用一旦引用了一个实体,就不能再引用其他实体
    • 常引用
    • 引用的使用场景
      • 引用做参数
      • 引用做返回值
    • 引用与指针的区别
  • 内联函数
    • 内联函数的概念
    • 内联函数的特性
  • 面试题:

引用

概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

其使用的基本形式为:类型& 引用变量名(对象名) = 引用实体。

#include <iostream>
using namespace std;
int main()
{int a = 10;int& b = a;//给变量a去了一个别名,叫bcout << "a = " << a << endl;//a打印结果为10cout << "b = " << b << endl;//b打印结果也是10b = 20;//改变b也就是改变了acout << "a = " << a << endl;//a打印结果为20cout << "b = " << b << endl;//b打印结果也是为20return 0;
}


注:引用类型必须和引用实体是同种类型.

引用的特性

一、引用在定义时必须初始化


//正确示例:
int a = 10;
int& b = a;//引用在定义时必须初始化//错误示例:
int c = 10;
int& d;//定义时未初始化
d = c;

二、一个变量可以有多个引用(多个别名)

例如:

int a = 10;
int& b = a;
int& c = a;
int& d = a;

三、引用一旦引用了一个实体,就不能再引用其他实体

例如:

	int a = 10;int& b = a;

此时,b已经是a的引用了,b不能再引用其他实体。如果你写下以下代码,想让b转而引用另一个变量c:

	int c = 20;b = c;//你的想法:让b转而引用c

但该代码并没有随你的意,该代码的意思是:将b引用的实体赋值为c,也就是将变量a的内容改成了20。

在这里插入图片描述

常引用

上面提到,引用类型必须和引用实体是同种类型的。但是仅仅是同种类型,还不能保证能够引用成功,我们若用一个普通引用类型去引用其对应的类型,但该类型被const所修饰,那么引用将不会成功。

int main()
{// 权限不能放大const int a = 10;//int& ra = a;    //该语句编译时会出错,a为常量const int& ra = a;//正确// 权限可以缩小//int& b = 10;    //该语句编译时会出错,10为常量const int& b = 10;//正确return 0;
}

我们可以将被const修饰了的类型理解为安全的类型,因为其不能被修改。我们若将一个安全的类型交给一个不安全的类型(可被修改),那么将不会成功。

引用的使用场景

引用做参数

还记得C语言中的交换函数,学习C语言的时候经常用交换函数来说明传值和传址的区别。现在我们学习了引用,可以不用指针作为形参了:

/交换函数
void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}

因为在这里a和b是传入实参的引用(也就是说起别名),我们将a和b的值交换,就相当于将传入的两个实参交换了。

引用做返回值

当然引用也能做返回值,但是要特别注意,我们返回的数据不能是函数内部创建的普通局部变量,因为在函数内部定义的普通的局部变量会随着函数调用的结束而被销毁。我们返回的数据必须是被static修饰或者是动态开辟的或者是全局变量等不会随着函数调用的结束而被销毁的数据。

先看下面这个例子:

int& Add(int a, int b)
{int c = a + b;return c;
}

在这里插入图片描述
我们会发现:这里的结果是一个随机值,这是因为:如果函数返回时,出了函数作用域,返回对象还未还给系统,则可以使用引用返回;如果已经还给系统了,则必须使用传值返回。

int& Add(int a, int b)
{static int c = a + b;return c;
}

在这里插入图片描述
在这里插入图片描述

引用与指针的区别

在语法概念上,引用就是一个别名,没有独立的空间,其和引用实体共用同一块空间。

int main()
{int a = 10;//在语法上,这里给a这块空间取了一个别名,没有新开空间int& ra = a;ra = 20;//在语法上,这里定义了一个pa指针,开辟了4个字节(32位平台)的空间,用于存储a的地址int* pa = &a;*pa = 20;return 0;
}

我们转到反汇编下,其实在底层实现上,引用实际是有空间的:
在这里插入图片描述
从汇编角度来看,引用的底层实现也是类似指针存地址的方式来处理的。

引用和指针的不同点:(重要!!!)

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 没有NULL引用,但有NULL指针
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 有多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  9. 引用比指针使用起来相对更安全

内联函数

在引出内联函数前,我们先用之前C语言学过的,用宏来定义一个Add函数。

#define Add(x,y) ((x)+(y))

测试一下:

int main()
{int ret1 = ADD(2, 3) * 5; // ((2)+(3))*5cout << "ret1=" << ret1 << endl;return 0;
}

在这里插入图片描述
这里我们用宏直接定义Add函数,看似代码先比较写一个Add函数来说间接了不少,但是用宏也会有缺点:
1、容易出错,语法细节多
2、不能调试
3、没有类型安全的检查

所以我们就用 enum const inline 来替代宏

其中:
enum const -> 宏常量
inline ->宏函数

而用inline用来修饰的函数就叫做内联函数。

内联函数的概念

inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数的使用可以提升程序的运行效率。
 我们可以通过观察调用普通函数和内联函数的汇编代码来进一步查看其优势:

不用inline修饰:

int Add(int a, int b)
{return a + b;
}
int main()
{int ret = Add(1, 2);return 0;
}

在这里插入图片描述
用inline修饰后:

int Add(int a, int b)
{return a + b;
}
int main()
{int ret = Add(1, 2);return 0;
}

在这里插入图片描述

下图左是以上代码的汇编代码,下图右是函数Add加上inline后的汇编代码:
在这里插入图片描述
从汇编代码中可以看出,内联函数调用时并没有调用函数这个过程的汇编指令。

内联函数的特性

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用。缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运
    行效率。

  2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为《C++prime》第五版关于inline的建议:
    在这里插入图片描述

  3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

面试题:

宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。

C++有哪些技术替代宏?

  1. 常量定义 换用const enum
  2. 短小函数定义 换用内联函数

相关文章:

【C++初阶(三)引用与内联函数】

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…...

RK3288 Android11 mini-pcie接口 4G模组EC200A适配(含自适应功能)

这里写目录标题 1、修改驱动内核配置①使能USBNET功能②使能 USB 串口 GSM、CDMA 驱动③使能 USB 的 CDC ACM模式④使能PPP功能 2、使用lsusb命令查看是否识别到usb接口的“EC200A”4G模组3、在drivers/usb/serial/option.c添加VID和PID信息①添加VID和PID定义②在option_ids 数…...

Windows安装Jenkins

JDK 11 以上 https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.20%2B8/OpenJDK11U-jdk_x64_windows_hotspot_11.0.20_8.msi https://www.jenkins.io/download/ 下载windows安装版本 授权用户administrator logon as services windows(server)安装…...

计算属性,侦听属性,方法区别及例子

计算属性、监听属性和方法都是Vue中的重要概念&#xff0c;但它们在功能和使用上有所不同&#xff1a; 计算属性&#xff1a;计算属性是基于依赖进行缓存的属性&#xff0c;可以根据其他数据动态计算得出。计算属性会根据依赖自动更新&#xff0c;但是只有在其所依赖的数据发生…...

Windows工业三防平板全功能NFC近距离感应一维/二维扫描

Windows系统工业三防平板电脑是一种在智慧工厂仓储物流、MES数采、车载设备、设备检测、自动化控制等领域广泛应用的先进设备。此外&#xff0c;它还在公共服务领域&#xff0c;如高速交通、物流运输、电力检测、公务执法、银行金融、船舶装备、户外勘测、建筑工程、汽车检测、…...

git远端协同开发、解决冲突、分支合并、gitlab使用、远程仓库回滚、为开源项目贡献代码、git工作流,git pull和git fetch,变基

协同开发 避免冲突 张三&#xff1a;改了 settings.py 第一行&#xff0c;提交了 李四&#xff1a;改了 settings.py 第二行&#xff0c;提交了 你也在改setting.py ,没有拉取代码&#xff0c;不知道他们提交了&#xff0c;动了第二行&#xff0c;但是跟李四代码不一样 你要…...

ims-go项目搭建

通过集成开发工具Goland创建项目 整合Gin框架&#xff0c;在终端中输入如下命令&#xff1a; go get -u github.com/gin-gonic/gin 整合Gorm&#xff0c;安装命令如下&#xff1a; go get -u gorm.io/gorm 安装sqlserver驱动&#xff0c;安装命令如下&#xff1a; go get -u…...

2022最新版-李宏毅机器学习深度学习课程-P26 Recurrent Neural Network

RNN 应用场景&#xff1a;填满信息 把每个单词表示成一个向量的方法&#xff1a;独热向量 还有其他方法&#xff0c;比如&#xff1a;Word hashing 单词哈希 输入&#xff1a;单词输出&#xff1a;该单词属于哪一类的概率分布 由于输入是文字序列&#xff0c;这就产生了一个问…...

【Qt控件之QButtonGroup】概述及使用

概述 QButtonGroup 类提供了一个容器来组织一组按钮部件。 QButtonGroup 提供了一个抽象容器&#xff0c;可以将按钮部件放置其中。它不提供此容器的可视表示&#xff08;请参见 QGroupBox&#xff0c;用于容器部件&#xff09;&#xff0c;而是管理组中每个按钮的状态。 一个…...

【开源分享】基于Html开发的房贷计算器,模仿新浪财经

房贷计算器是一种房贷计算的在线计算Web应用&#xff0c;按用户选择的贷款类型、贷款金额、期限、利率可计算得出每月月供参考、支付利息、还款总额这些信息。本文模仿新浪财经开发的房贷计算器。 作品预览 https://fangdai.gitapp.cn 源码地址 https://github.com/geeeeeee…...

ftp文件上传缓慢问题

问题描述 某环境下&#xff0c;通过vsftp上传文件缓慢。 问题分析 这个问题是由于服务器DNS导致&#xff0c;如果在内网机器中&#xff0c;配置了公网的DNS或者其他不能链接的DNS&#xff0c;会导致上传缓慢。 解决方案 目前有两种解决方式&#xff0c;任选其一即可&#…...

【周末闲谈】VR新视界,“眼”见未来

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 系列目录 ✨第一周 二进制VS三进制 ✨第二周 文心一言&#xff0c;模仿还是超越&#xff1f; ✨第二周 畅想AR 文章目录 系列目录前言虚拟现实(VR)技术虚拟现实技术的原理虚拟现实技术发…...

CSRF和XSS是什么?

CSRF&#xff08;Cross-site request forgery&#xff09;&#xff1a;跨站请求伪造。 用户是网站A的注册用户&#xff0c;且登录进去&#xff0c;于是网站A就给用户下发cookie。 满足条件&#xff1a; &#xff08;1&#xff09;登录受信任网站A&#xff0c;并在本地生成Cook…...

【Machine Learning】01-Supervised learning

01-Supervised learning 1. 机器学习入门1.1 What is Machine Learning?1.2 Supervised learning1.3 Unsupervised learning 2. Supervised learning2.1 单元线性回归模型2.1.1 Linear Regression Model&#xff08;线性回归模型&#xff09;2.1.2 Cost Function&#xff08;代…...

《视觉 SLAM 十四讲》V2 第 8 讲 视觉里程计2 【如何根据图像 估计 相机运动】【光流 —> 直接法】

OpenCV关于 光流的教程 文章目录 第 8 讲 视觉里程计 28.2 光流8.3 实践&#xff1a; LK 光流 【Code】本讲 CMakeLists.txt 8.4 直接法8.5 实践&#xff1a; 双目的稀疏直接法 【Code】8.5.4 直接法的优缺点 习题 8√ 题1 光流方法题2题3题4题5 第 8 讲 视觉里程计 2 P205 …...

Unity DOTS System与SystemGroup概述

最近DOTS终于发布了正式的版本, 我们来分享以下DOTS里面System关键概念&#xff0c;方便大家上手学习掌握Unity DOTS开发。 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验呀&#xff01; System是迭代计算与处理World中的…...

IDEA使用内置database数据库连接mysql报错:javax.net.ssl.SSLHandshakeException

参考一些博客的方式&#xff1a; 使用idea内置database连接数据库报错javax.net.ssl.SSLHandshakeException: No appropriate protocol_idea database ssl_你当像山的博客-CSDN博客 他们的方式是&#xff1a;在url后添加useSSLfalse 介绍另外一种方式&#xff1a; 点击datab…...

从Flink的Kafka消费者看算子联合列表状态的使用

背景 算子的联合列表状态是平时使用的比较少的一种状态&#xff0c;本文通过kafka的消费者实现来看一下怎么使用算子列表联合状态 算子联合列表状态 首先我们看一下算子联合列表状态的在进行故障恢复或者从某个保存点进行扩缩容启动应用时状态的恢复情况 算子联合列表状态主…...

CSS3 按钮

创建 CSS3 按钮可以通过组合样式属性和伪类来实现 <!DOCTYPE html> <html> <head><link rel"stylesheet" type"text/css" href"styles.css"> </head> <body><button class"basic-button">…...

STM32 BootLoader设置

编写bootloader程序&#xff1a; 直接复制下面代码到自己程序中。 typedef void (*iapfun)(void); //定义一个函数类型的参数. iapfun jump2app; //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) {MSR MSP, r0 //set Main Stack valueBX r14 }//跳转到…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学

一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件&#xff0c;其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时&#xff0c;价带电子受激发跃迁至导带&#xff0c;形成电子-空穴对&#xff0c;导致材料电导率显著提升。…...