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

02.C++入门基础(下)

1.函数重载

C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。C语言是不支持同一作用域中出现同名函数的。
1、参数类型不同
2、参数个数不同
3、参数类型顺序不同
注意:返回值不同不能作为重载条件,因为调用时也无法区分
只是返回类型不同的话,下面编译就会报错
这种情况也是不行的,下面两个函数构成重载,但第二个f1函数使用了缺省参数,f1()调用时会报错,存在歧义,编译器不知道调用谁。

2.引用

2.1引用的概念和定义

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵,江湖上人称"黑旋风";林冲,外号豹子头;
类型& 引用别名 = 引用对象;
C++中为了避免引入太多的运算符,会复用C语言的一些符号,比如前面的<< 和 >>,这里引用也和取地址使用了同一个符号&,大家注意使用方法角度区分就可以。
如下图:引用其实就是取别名,本质上还是a,只不过给他起了个外号,同样,在对a引用时,改变引用也会改变它本身。

2.2引用的特性

引用在定义时必须初始化
一个 变量可以有多个引用
引用 旦引用一个实体,再不能引用其他实体
注意:引用必须初始化

2.3引用的使用

引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。
引用传参跟指针传参功能是类似的,引用传参相对更方便一些。
引用返回值的场景相对比较复杂,我们在这里简单讲了一下场景,还有一些内容后续类和对象中会继续深入讲解。
引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向,Java的引用可以改变指向。
些主要用C代码实现版本数据结构教材中,使用C++引用替代指针传参,目的是简化程序,避开复杂的指针。
先来看一下引用传参
就比如栈,其他接口就不去一一实现了,如果我们要修改栈顶的话,可以直接对STTop()函数的返回值进行操作,因为它返回的是栈顶值的引用,我们改变它的引用就是改变栈顶本身,不然还要去实现修改栈顶数据的接口,就显得繁琐了
int& STTop(ST& rs)
{assert(rs.top > 0);return rs.a[rs.top];
}STTop(st1) += 10;
cout << STTop(st1) << endl;

2.4const引用

可以引用一 个const对象,但是必须用const引用。const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。
不过需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样一些场景下a*3的结果保存在一个临时对象中, int& rd = d 也是类似,在类型转换中会产生临时对象存储中间值,也就是,rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里就触发了权限放大,必须要用常引用才可以。
所谓临时对象就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象,C++中把这个未命名对象叫做临时对象。
我们用const修饰变量a,那么a只能读不能写,如果我们对a引用ra,如果不加const修饰,我们就可以对ra进行读写操作,权限就放大了,这样就矛盾了,因为ra是a的引用(别名),a只能读不能写,那么ra也应该只能读不能写,所以编译就会报错。权限不能放大但是可以缩小,就像b,对b引用rb,并用const修饰,那么b可读可写,rb只能读不能写。
const引用可以直接引用一个数字常量,然后就是上面提到的第二点。

2.5指针和引用的关系

总结一下指针和引用:

C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。
语法概念上引用是一个变量的取别名不开空间,指针是存储一个变量地址,要开空间。
引用在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
引用在初始化时引用一个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象。
引用可以直接访问指向对象,指针需要解引用才是访问指向对象。
sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8字节)
指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全一些。

3.inline

用“ inline”关键字修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数就需要建立栈帧了,就可以提高效率。
inline对于编译器而言只是一个建议,也就是说,你加了inline编译器也可以选择在调用的地⽅不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适用于频繁调用的短小函数,对于递归函数,代码相对多一些的函数,加上inline也会被编译器忽略。
C语言实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不方便调试,C++设计了inline目的就是替代C的宏函数。
vs编译器 debug版本下面默认是不展开inline的,这样方便调试。
inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。
内联函数能够提高程序效率,主要归因于以下几个方面:
 
1. 减少函数调用开销:当普通函数被调用时,会产生一系列额外的操作,比如将参数压入栈、保存当前指令地址、跳转至函数起始地址等。而内联函数在编译阶段,会将函数体的代码直接替换到调用处,避免了这些额外的操作,从而节省了时间。
2. 避免上下文切换:函数调用可能涉及到不同的指令地址和上下文切换。使用内联函数可以消除这种切换,使得程序的执行更加流畅,减少了 CPU 因切换上下文而产生的延迟。
3. 更好的优化机会:由于内联函数的代码直接嵌入到调用处,编译器能够更好地对整个代码段进行优化。例如,可以更有效地利用寄存器、进行指令重排等,以提高程序的执行速度。
4. 减少缓存缺失:函数调用可能导致跨越不同的缓存行,增加缓存缺失的概率。内联函数减少了这种可能性,因为相关的代码在物理上更加接近,提高了缓存的命中率,进而提高了程序的性能。
 
综上所述,内联函数通过消除函数调用的额外开销、优化代码布局和利用缓存等方式,有效地提高了程序的执行效率。但需要注意的是,内联函数并非适用于所有情况,对于复杂的大型函数,内联可能会导致代码膨胀等问题。

4.nullptr

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif
C++中NULL可能被定义为字面常量0,或者C中被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,本想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,调用了f(int x),因此与程序的初衷相悖。f((void*)NULL)调用会报错。
C++11中引入nullptr,nullptr是一个特殊的关键字,nullptr是一种特殊类型的字面量,它可以转换成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,而不能被转换为整数类型。
在C++中NULL被定义为字面常量0,我们可以显式转换为(int*),如果强制转换为(void*),则会报错。
这是为什么呢?
在 C++中, null 实际上被定义为 0 。C++是一种强类型语言,不允许将 void* 类型的指针隐式转换为其他类型的指针。
 
虽然在 C 语言中可以进行这样的隐式转换,但 C++对类型要求更严格。任何指针类型可以隐式转换为 void* ,但反过来则必须进行强制类型转换。
 
例如,以下代码在 C++中会报错:
 
//cppint* a = null; 
void* b = null; 
char* c = null; 
c = a; // 出错 
b = a; // 通过 
c = b; // 出错 
如果要进行赋值,必须进行显式转换:
 
//cppint* a = null; 
void* b = null; 
char* c = null; 
c = (char*)a; // 通过 
b = a; // 通过 
c = (char*)b; // 通过 
这样的设计是为了增强类型安全性,避免潜在的类型错误和歧义。在 C++11 中,引入了 nullptr 关键字来更明确地表示空指针。 nullptr 并非整型类别,也不是指针类型,但能转换成任意指针类型。使用 nullptr 可以更清晰地表达空指针的意图,并且避免了 null 可能导致的一些二义性问题。例如,如果有重载的函数:
 
//cppvoid func(int x); 
void func(char* y); 
调用 func(nullptr) 会明确地调用 func(char* y) ,而使用 func(null) 则可能会因为 null 被视为 0 而产生歧义。
所以我们可以用nullptr来解决这一问题,可以更清晰的表达空指针的意图。

相关文章:

02.C++入门基础(下)

1.函数重载 C支持在同一作用域中出现同名函数&#xff0c;但是要求这些同名函数的形参不同&#xff0c;可以是参数个数不同或者类型不同。这样C函数调用就表现出了多态行为&#xff0c;使用更灵活。C语言是不支持同一作用域中出现同名函数的。 1、参数类型不同 2、参数个数不同…...

【数据结构】探索排序的奥秘

若有不懂地方&#xff0c;可查阅我之前文章哦&#xff01; 个人主页&#xff1a;小八哥向前冲~_csdn博客 所属专栏&#xff1a;数据结构_专栏 目录 排序的概念 几种排序方法介绍 冒泡排序 选择排序 插入排序 堆排序 向上调整建堆排序 向下调整建堆排序 希尔排序 快速…...

数据结构面试知识点总结3

#来自ウルトラマンティガ&#xff08;迪迦&#xff09; 1 线性表 最基本、最简单、最常用的一种数据结构。一个线性表是 n 个具有相同特性的数据元素的有限序列。 特征&#xff1a;数据元素之间是一对一的逻辑关系。 第一个数据元素没有前驱&#xff0c;称为头结点&#xff1…...

python-爬虫实例(5):将进酒,杯莫停!

目录 前言 将进酒&#xff0c;杯莫停&#xff01; 一、浇给 二、前摇 1.导入selenium库 2.下载浏览器驱动 三、爬虫四步走 1.UA伪装 2.获取url 3.发送请求 4.获取响应数据进行解析并保存 总结 前言 博主身为一个农批&#xff0c;当然要尝试爬取王者荣耀的东西啦。 将进…...

AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理

AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 目录 AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 一、简单介绍 二、Transformer 1、模型架构 2、应用场景 3、Hugging …...

十大排序的稳定性和时间复杂度

十大排序算法的稳定性和时间复杂度是数据结构和算法中的重要内容。 以下是对这些算法的稳定性和时间复杂度的详细分析&#xff1a; 稳定性 稳定性指的是排序算法在排序过程中是否能够保持相等元素的原始相对顺序。根据这个定义&#xff0c;我们可以将排序算法分为稳定排序和…...

【系列教程之】1、点亮一个LED灯

1、点亮一个LED灯 作者将狼才鲸创建日期2024-07-23 CSDN教程目录地址&#xff1a;【目录】8051汇编与C语言系列教程本Gitee仓库原始地址&#xff1a;才鲸嵌入式/8051_c51_单片机从汇编到C_从Boot到应用实践教程 本源码包含C语言和汇编工程&#xff0c;能直接在电脑中通过Keil…...

搜维尔科技:Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作

Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作 搜维尔科技&#xff1a;Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作...

机器学习 | 阿里云安全恶意程序检测

目录 一、数据探索1.1 数据说明1.2 训练集数据探索1.2.1 数据特征类型1.2.2 数据分布1.2.3 缺失值1.2.4 异常值1.2.5 标签分布探索 1.3 测试集探索1.3.1 数据信息1.3.2 缺失值1.3.3 数据分布1.3.4 异常值 1.4 数据集联合分析1.4.1 file_id 分析1.4.2 API 分析 二、特征工程与基…...

python打包exe文件-实现记录

1、使用pyinstaller库 安装库&#xff1a; pip install pyinstaller打包命令标注主入库程序&#xff1a; pyinstaller -F.\程序入口文件.py 出现了一个问题就是我在打包运行之后会出现有一些插件没有被打包。 解决问题&#xff1a; 通过添加--hidden-importcomtypes.strea…...

基本的DQL语句-单表查询

一、DQL语言 DQL(Data Query Language 数据查询语言)。用途是查询数据库数据&#xff0c;如SELECT语句。是SQL语句 中最核心、最重要的语句&#xff0c;也是使用频率最高的语句。其中&#xff0c;可以根据表的结构和关系分为单表查询和多 表联查。 注意&#xff1a;所有的查询…...

Vue3 对比 Vue2

相关信息简介2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09; 2 年多开发, 100位贡献者, 2600次提交, 600次 PR、30个RFC Vue3 支持 vue2 的大多数特性 可以更好的支持 Typescript&#xff0c;提供了完整的…...

2024中国大学生算法设计超级联赛(1)

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;彩笔ACMer一枚。 &#x1f3c0;所属专栏&#xff1a;杭电多校集训 本文用于记录回顾总结解题思路便于加深理解。 &#x1f4e2;&#x1f4e2;&#x1f4e2;传送门 A - 循环位移解…...

offer题目51:数组中的逆序对

题目描述&#xff1a;在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对。输入一个数组&#xff0c;求出这个数组中的逆序对的总数。例如&#xff0c;在数组{7,5,6,4}中&#xff0c;一共存在5个逆序对&#xff0c;分别是(7…...

45、PHP 实现滑动窗口的最大值

题目&#xff1a; PHP 实现滑动窗口的最大值 描述&#xff1a; 给定一个数组和滑动窗口的大小&#xff0c;找出所有滑动窗口里数值的最大值。 例如&#xff1a; 如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3&#xff0c; 那么一共存在6个滑动窗口&#xff0c; 他们的最大值…...

【计算机视觉】siamfc论文复现实现目标追踪

什么是目标跟踪 使用视频序列第一帧的图像(包括bounding box的位置)&#xff0c;来找出目标出现在后序帧位置的一种方法。 什么是孪生网络结构 孪生网络结构其思想是将一个训练样本(已知类别)和一个测试样本(未知类别)输入到两个CNN(这两个CNN往往是权值共享的)中&#xff0…...

数学建模学习(111):改进遗传算法(引入模拟退火、轮盘赌和网格搜索)求解JSP问题

文章目录 一、车间调度问题1.1目前处理方法1.2简单案例 二、基于改进遗传算法求解车间调度2.1车间调度背景介绍2.2遗传算法介绍2.2.1基本流程2.2.2遗传算法的基本操作和公式2.2.3遗传算法的优势2.2.4遗传算法的不足 2.3讲解本文思路及代码2.4算法执行结果&#xff1a; 三、本文…...

Golang | Leetcode Golang题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; const addition, subtraction, multiplication -1, -2, -3func diffWaysToCompute(expression string) []int {ops : []int{}for i, n : 0, len(expression); i < n; {if unicode.IsDigit(rune(expression[i])) {x : 0for ; i < n &…...

Unity客户端接入原生Google支付

Unity客户端接入原生Google支付 1. Google后台配置2. 开始接入Java部分C#部分Lua部分 3. 导出工程打包测试参考踩坑注意 1. Google后台配置 找到内部测试&#xff08;这个测试轨道过审最快&#xff09;&#xff0c;打包上传&#xff0c;这个包不需要接入支付&#xff0c;如果已…...

Spring Cloud之五大组件

Spring Cloud 是一系列框架的有序集合&#xff0c;为开发者提供了快速构建分布式系统的工具。这些组件可以帮助开发者做服务发现&#xff0c;配置管理&#xff0c;负载均衡&#xff0c;断路器&#xff0c;智能路由&#xff0c;微代理&#xff0c;控制总线等。以下是 Spring Cl…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...