C嘎嘎~~【初识C++ 中篇】

news2025/1/12 18:09:04

初识C++ 中篇

  • 1.缺省参数
  • 2.函数重载
    • 2.1函数重载的概念
    • 2.2函数重载的原理
  • 3.auto关键字
    • 3.1类型别名思考(typedef)
    • 3.2auto的简介
    • 3.3auto的使用规则
    • 3.4 auto不能推导的场景
  • 4.基于范围的for循环
    • 4.1范围for的语法
    • 4.2范围for的使用条件

1.缺省参数

缺省参数是 声明或定义函数时 为 函数的参数指定一个缺省值。在调用该函数时, 如果没有指定实参则采用该形参的缺省值, 否则使用指定的实参

void func(int a = 5)
{
	cout << a << endl;

}

int main()
{
	func(); // 5
	func(10); // 10

	return 0;

}

  • 关于缺省的一些分类, 做了下面的总结:


有一些老铁, 就会问:为啥半缺省的时候要从左至右传参, 从右至左缺省啊??

  • 首先, 我们要明确一点,缺省是从右至左的, 那我们如果传参的时候也按照同样的顺序进行传参, 如果传参的个数和缺省的个数是一样的, 那么缺省的意义是什么呢?

下面的代码是缺省函数的一个应用:

typedef struct Stack
{
	int* a;
	int top;
	int size;
	int capacity;
}ST;

void STInit(ST* head, int DEFAULT = 10) 
{
	int* tem = (int*)malloc(sizeof(int*) * DEFAULT);
	if (tem == NULL)
	{
		perror("malloc fail");
		return;
	}

	head->a = tem;
	head->capacity = DEFAULT;

}

int main()
{
	ST st;
	STInit(&st); // 使用10
	STInit(&st, 20); // 使用20

	return 0;

}

在单链表、 栈 、 队列这些线性结构中, 初始化要给多少空间是拿捏不准的,如果给大了, 用户用的少; 如果给小,用户不够用,还要增容(增容是很浪费空间 和 时间的)。所以, 我们想能不能有这样的情况: 先给一个默认值, 如果用户感觉小了, 再给大一点; 如果感觉适中, 就用这个默认值。
刚学的缺省参数就派上了用场, 这样多方便啊。 在C语言中, 可以用 # define MIN 10; (宏)来替代一些作用, 但是他不能像缺省参数这样可以随意改变大小啊?

注意:

  1. 缺省参数必须从右至左依次来给, 不能间隔着给
  2. 缺省值一般是常量、全局变量(这个一般不推荐)
  3. 如果声明和定义分明(声明在.h 文件中, 定义在.cpp 文件中),缺省参数不能在函数定义 和 声明中同时给的(缺省参数是给声明的, 因为在函数的编译环节, 编译器看到的是函数声明,在最后的链接过程,才找到定义);如果函数的声明和定义是在同一个文件中, 可以给声明,也可以给定义(因为在这个过程中, 函数的编译 和 链接过程是一起进行的)

2.函数重载

中国文化博大精深, 历史源远流长。在我们的日常生活中, 有许多词语一词多义, 单拎出来,不知道是什么意思,要借助上下文来判断该词语的真正含义, 即改词被重载了。

2.1函数重载的概念

函数重载: 是C++中函数的一种特殊情况, 允许在同一作用域中声明几个功能类似的同名函数, 这些同名函数的形参列表(参数个数、 类型 或 类型顺序)不同, 常用来处理实现功能类似数据类型不同的问题

  1. 参数个数不同
int Sub(int a, int b)
{
	cout << "Sub(int a, int b)" << endl;
	return a - b;

}

int Sub(int a)
{
	cout << "Sub(int a)" << endl;
	return a;

}

int main()
{
	Sub(5); // Sub(int a)
	Sub(10, 8); // Sub(int a, int b)

	return 0;
}
  1. 类型顺序不同
int Sub(int a, int b)
{
	cout << "Sub(int a, int b)" << endl;
	return a - b;

}

int Sub(int a, double b)
{
	cout << "Sub(int a, double b)" << endl;
	return a;

}

int main()
{
	Sub(5, 1.5); // Sub(int a, double b)
	Sub(10, 8); // Sub(int a, int b)

	return 0;
}
  1. 类型不同
int Sub(double a, int b)
{
	cout << "Sub(double a, int b)" << endl;
	return a - b;

}

int Sub(int a, double b)
{
	cout << "Sub(int a, double b)" << endl;
	return a;

}

int main()
{
	Sub(5, 1.5); // Sub(int a, double b)
	Sub(1.5, 8); // Sub(double a, int b)

	return 0;
}

有些老铁看到这里, 忍不住问了: 那我如果函数返回类型不同, 但函数的形参列表相同,构不构成函数重载??

  • 首先, 上面所说的构成函数重载的条件是形参列表不同, 即形参的类型、 形参的个数 或 形参类型的顺序不同;
  • 其次, 如果想看原理性的答案, 请移步下面 “函数重载的原理”

2.2函数重载的原理



C++的函数重载,依赖于C++对函数进行了修饰(不同的平台,修饰规则不同),然后才会自动匹配类型/ 自动识别类型。
通过下面的一张图, 使我们对C 和 C++ 的函数调用有个更深刻的理解


来一个面试题来检查一下我们上面的两个内容:

void Add(int a = 0)
{
	cout << "Add(int a = 0)" << endl;
}

void Add()
{
	cout << "Add()" << endl;
}

上面的代码能不能构成重载?
首先, 能构成重载(因为参数的个数不同)
其次, 无参调用时,会存在歧义, 重载不明确

3.auto关键字

3.1类型别名思考(typedef)

随着程序越来越复杂, 程序中用到的类型也越来越复杂, 经常体现在:

  1. 类型难于拼写
  2. 含义不明确导致容易出错

以后我们要学的迭代器很长、也很容易写错, 我们用atuo(自动匹配类型)就很舒服。 有些聪明的老铁就会反问:我们用 typedef 也不是一样的效果嘛? 使用 typedef 给类型取别名 确实是可以简化代码, 但是也有些新的问题,见下面的代码:
typedef int* pint;


int main()
{
	const pint p1; // 能否编译成功
	const pint* p2; // 能否编译成功

	return 0;
}

在编程时, 通常要给变量 或 表达式 赋初值, 这就要求在声明变量的时候要清楚地知道表达式的类型, 然而有时候要做到这一点并非是很容易的, 因此C++给 auto 赋予了新的含义。

3.2auto的简介

C++11中, 标准委员会赋予了 auto 全新的含义: auto 不再是 一个存储类型指示符, 而是作为一个全新的类型指示符来指示编译器, auto 声明的变量必须有编译器在编译时期推到而得。简而言之, 在新的C++标准中, 使用 auto 可以由推导变量 或者是表达式的类型。
通过下面的代码, 我们来清楚地看一下:

double Add(int a, double b)
{
	return a + b;

}

int main()
{
	int a;
	auto b = 2.1;
	auto c = 'a';

	cout << typeid(a).name() << endl; // int
	cout << typeid(b).name() << endl; // double
	cout << typeid(c).name() << endl; // char
	cout << typeid(Add).name() << endl; // double __cdecl(int,double)

	return 0;

}

总结:

  1. 使用 auto 定义变量的时候必须要对其进行初识化, 在编译阶段, 编译器需要根据初始化来推导 auto 的实际类型
  2. auto 并非是一种 “类型” 的声明, 而是一个类型声明时的 “占位符”, 编译器在编译时会将 auto 这个东东 替换成 变量的实际类型

3.3auto的使用规则

  1. auto 与指针 和 引用结合起来使用

先让我们来看一下代码:

int main()
{
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;

	cout << typeid(a).name() << endl; // int * __ptr64
	cout << typeid(b).name() << endl; // int * __ptr64
	cout << typeid(c).name() << endl; // int

	*a = 20;
	*b = 40;
	c = 50;
	cout << a << " " << *a << endl; // 00000030CB8FFA44 50
	cout << b << " " << *b << endl; // 00000030CB8FFA44 50
	cout << &c << " " << c << endl; // 00000030CB8FFA44 50

	return 0;

}
  • 如上图结果所知: 用 auto 声明指针类型时, auto 和 auto* 是一样的,没有任何区别。但是 auto 声明引用类型时, 必须要加&。
  1. 在同一行定义多个变量
int main()
{
	auto a = 1, b = 2; // 能够编译成功
	auto c = 1, d = 4.0; // 编译失败, c 和 d的初始化的类型是不一样的

	return 0;
}
  • 用 auto 在同一行定义多个变量时, 这些变量必须是相同的类型, 只要有变量的类型有不一样的,就会编译错误。
    因为编译器实际上只对第一个类型进行推导(从左至右),然后用推导出来的类型来定义其他变量。

3.4 auto不能推导的场景

  1. auto 不能作为函数的参数(肯定是形参啊)
int Sub(auto a); // 会编译错误, auto 不能作为形参参数, 因为编译器不能对 a 的实际类型进行推导

int main()
{
	int a = 0;
	Sub(a);

	return 0;
}
  1. auto 不能直接用来声明数组
int main()
{
	int a[] = { 1, 2, 3 };
	auto b[] = { 4, 5, 6 }; // 即使有[],编译器也不能进行推导

	return 0;
}
  1. auto 在实际中最常用的优势用法是C++ 提供的新式for 循环, 还有lambda表达式等进行配合使用

4.基于范围的for循环

这个数组的范围是确定的啊, 为啥会报越界的error啊??
不理解、不理解!!
祖师爷,来出一个东东来解决一下吧
星光荡开宇宙, 范围for循环闪耀登场

4.1范围for的语法

对于一个有范围的集合而言, 对程序员来说循环的范围是多余的, 有时候还容易犯错误!!因此, 我们的祖师爷就引入了基于范围的for循环。
基本构成: 原本for循环()内的内容变成 由冒号(:)分成的两部分; (类型 : 有范围的集合)

让我们通过下面的代码来清楚地看一下:

int main()
{
	int arr[] = { 1,2,3,4,5 };
	for (int a : arr)
	{
		cout << a << " ";
	}
	cout << endl; // 1 2 3 4 5

	for (auto a : arr)
	{
		cout << a << " ";
	}
	cout << endl; // 1 2 3 4 5

	for (auto& a : arr)
	{
		a *= 2; // 将每个数都乘2
		cout << a << " ";
	}
	cout << endl; // 2 4 6 8 10

	return 0;

}

总结:

  1. auto 和 引用(&)跟 范围for循环 配合使用是非常的香
  2. 与普通循环类似, 可以用 continue 来结束本次循环, 也可以用 break 来跳出整个循环

4.2范围for的使用条件

  1. for循环迭代的范围必须是确定的

对于数组而言, 就是数组中第一个元素 和 最后一个元素 的范围
对于类而言, 应该提供begin 和 end的范围, begin 和 end 就是循环迭代的范围

void test(int arr[]) // 这个就是错误的, 因为这里arr是一个指针, 导致循环的范围是不确定的
{
	for (auto a : arr)
	{
		cout << a << end;
	}
}
  1. 迭代的对象要实现 ++ 和 == 的操作(关于迭代器的问题, 这个以后再讲)

行路难, 行路难, 多歧路, 今安在?
长风破浪会有时, 直挂云帆济沧海。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02_2440soc_内存地址映射和选择,寄存器地址的选择

大多数arm芯片从0开始启动 nand_flash控制器外接nand_flash 256M cpu直接接nor_flash 2M nor_flash启动时候 nor_flash上面烧了bin文件 nor_flash基地址为0 cpu直接读nor上的第一个指令(前4字节),执行 cpu继续读取其他指令 执行 如果使用nor启动,片内的sram的地址就是 0x4000…

实战:内存分配与回收策略

java技术体系的自动内存管理&#xff0c;最根本的目标是自动化地解决两个问题&#xff1a;自动给对象分配内存以及自动回收分配给对象的内存。 1 前置知识 1.1 Minor GC 与Full GC Minor GC: 新生代GC&#xff0c;是指发生新生代的垃圾收集动作。Minor GC非常频繁&#xff0…

mac m1安装stable-diffusion

安装stable-diffusion 安装Homebrew安装python及其他依赖下载model安装Stable-Diffusion-WebUI执行./webui.sh作图http://127.0.0.1:7860 安装Homebrew 查询是否安装 brew -v安装 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.…

14.网络爬虫—selenium详讲

网络爬虫—selenium详讲 一selenium简介Selenium 的优点 二安装模块三设置浏览器驱动确认版本&#xff1a;查找对应驱动下载驱动 四使用模块selenium选取元素方法selenium嵌套页面元素定位selenium网页下拉selenium下拉表选择selenium行为链selenium等待 五错误解决方案六结束语…

[oeasy]python0135_python_语义分析_ast_抽象语法树_abstract_syntax_tree

语义分析_抽象语法树_反汇编 回忆 上次回顾了一下历史 python 是如何从无到有的看到 Guido 长期的坚持和努力 python究竟是如何理解 print(“hello”)的&#xff1f;这些ascii字母如何被组织起来执行&#xff1f; 纯文本 首先编写Guido的简历 print("1982------Gui…

LeetCode刷题集(五)(LeetCode1.两数之和)

学习目标&#xff1a; 掌握LeetCode第一题两数之和 学习内容&#xff1a; LeetCode第一题两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会…

ASEMI代理AD9951YSVZ原装ADI车规级AD9951YSVZ

编辑&#xff1a;ll ASEMI代理AD9951YSVZ原装ADI车规级AD9951YSVZ 型号&#xff1a;AD9951YSVZ 品牌&#xff1a;ADI/亚德诺 封装&#xff1a;HTQFP-48 批号&#xff1a;2023 引脚数量&#xff1a;48 安装类型&#xff1a;表面贴装型 AD9951YSVZ汽车芯片 特征 400 MS…

shell编程实例 — 实现4G开机自动运行,实时监测,断线自动重拨》

shell编程实例 — 实现4G开机自动运行&#xff0c;实时监测&#xff0c;断线自动重拨》 往事只能回味味道 于 2021-11-20 02:30:53 发布831 收藏 1 分类专栏&#xff1a; shell 文章标签&#xff1a; ubuntu linux udp 版权 ​编辑shell专栏收录该内容 3 篇文章0 订阅 订阅…

Mysql日志系统-InnoDB引擎层

一、redo log日志 接下来的两个日志&#xff0c;是innodb为解决不同问题而引出的两类日志文件。 redo log&#xff08;重做日志&#xff09;的设计主要是为了防止因系统崩溃而导致的数据丢失&#xff0c;其实解决因系统崩溃导致数据丢失的思路如下&#xff1a; 1、每次提交事务…

SpringBoot解决用户重复提交订单(方式二:通过Redis实现)

文章目录 前言1、方案实践1.1、引入Redis依赖1.2、添加Redis环境配置1.3、编写获取请求唯一ID的接口&#xff0c;同时将唯一ID存入redis 1.4、编写服务验证逻辑&#xff0c;通过 aop 代理方式实现1.5、在相关的业务接口上&#xff0c;增加SubmitToken注解即可 2、小结 前言 在…

华润数科、京东科技、京彩未来携手共进,求解“科技×产业”最大值

4月18日&#xff0c;华润数科、京东科技、京彩未来三方代表在中国深圳签署三方合作协议。面向产业数字化的市场机遇&#xff0c;华润数科物联网事业部总经理刘楚明先生表示&#xff0c;华润数科作为华润集团重点培育的数字科技业务单元&#xff0c;基于技术优势及资源整合能力&…

在SAP中使用QUERY

在SAP中使用QUERY 一、SAP query介绍 ​ QUERY是SAP提供的方便无编程基础用户的报表工具&#xff0c;使用图形化的界面&#xff0c;让用户托托拽拽就能轻松完成报表编写。我们可以将Query理解成QuickView的高级版本&#xff0c;它在QuickView的基础上增加的功能有&#xff1a…

一、摄影基础课

目录 第一章 控制曝光1. 曝光及曝光三要素1.1 曝光1.2 光圈1.3 快门1.4 感光度&#xff08;ISO&#xff09;1.5 曝光三要素之间的关系 2. 曝光模式3. 测光模式4. 曝光补偿 第二章 控制对焦1. 对焦区域2. 对焦模式 第三章 控制色彩 第一章 控制曝光 1. 曝光及曝光三要素 1.1 曝…

尚硅谷大数据技术Zookeeper教程-笔记01【Zookeeper(入门、本地安装、集群操作)】

视频地址&#xff1a;【尚硅谷】大数据技术之Zookeeper 3.5.7版本教程_哔哩哔哩_bilibili 尚硅谷大数据技术Zookeeper教程-笔记01【Zookeeper(入门、本地安装、集群操作)】尚硅谷大数据技术Zookeeper教程-笔记02【服务器动态上下线监听案例、ZooKeeper分布式锁案例、企业面试真…

外包干了4年,直接废了···

有一说一&#xff0c;外包没有给很高的薪资&#xff0c;是真不能干呀&#xff01; 先说一下自己的情况&#xff0c;大专生&#xff0c;19年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0…

[java/初学者]java常用API(1)——包装类

前言 在学习本课题之前&#xff0c;我们首先需要知道什么是API。 API&#xff0c;即Application Programming Interface&#xff0c;中文名称是“应用程序接口"&#xff0c; 这些接口就是"jdk所提供"给我们使用的类&#xff0c;我们不需要去深究它是如何实现…

STM32+EC20实现4G无线通信

EC20是一款集成度非常高的4G无线通信模块&#xff0c;支持多种常见通信频段&#xff0c;能满足几乎所有的M2M(MachinetoMachine)应用需求。模块支持TCP/UDP/FTP等一众网络协议&#xff0c;内置多星座高精度定位GNSS接收机&#xff0c;快速提供准确的经纬度信息&#xff0c;UART…

vscode java环境扩展

下载安装jdk: Java Downloads | Oracle 下载安装maven: Maven – Download Apache Maven windows系统选择 Binary zip archive maven目录中的conf文件中有一个settins.xml文件 镜像&#xff08;mirrors&#xff09;二选一 <mirror><id>nexus-aliyun</…

影视动画设计有些SCI期刊推荐? - 易智编译EaseEditing

以下是几本影视动画设计方向的SCI期刊&#xff1a; ACM Transactions on Graphics: 该期刊是ACM&#xff08;Association for Computing Machinery&#xff0c;美国计算机协会&#xff09;下的一个子刊&#xff0c;涵盖了计算机图形学和交互技术等领域&#xff0c;也包括了动…

虚拟化技术 — 硬件辅助的虚拟化技术

目录 文章目录 目录硬件辅助的虚拟化技术概览CPU 虚拟化技术基于二进制翻译的全虚拟化技术&#xff08;Full-Virtualization&#xff09;需要改造 GuestOS 的半虚拟化技术&#xff08;Para-Virtualization&#xff09;Intel VT-x 硬件辅助的虚拟化技术&#xff08;Hardware-ass…