C++核心知识回顾(函数&参数、异常、动态分配)
复习C++的核心知识
函数与参数
传值参数、模板函数、引用参数、常量引用参数
传值参数
int abc(int a,int b,int c) {
return a + b * c;
}
a、b、c是函数abc的形参,下面语句中调用函数abc:
z = abc(2,x,y);
2、x、y就是分别于a b c对应的实参,形参a、b、c实际上是传值参数,在运行时,函数abc执行前,将实参复制给形参,复制过由形参类型的复制构造函数来完成,如果类型不同会进行转换。当函数运行结束后,形参类型的析构函数负责释放形式参数
模板函数
将上述abc函数改写的更具有通用性,参数类型是一个变量,其值由编译器决定,即使用模板语句
template<class T>
T abc(T a,T b,T c) {
return a + b * c;
}
引用参数
使用形参会增加程序运行的时间,上述函数中,当a、b、c是传值参数时,一进入函数调用,类型T的复制构造函数就会启用,返回时,析构函数就会启用,如果T是比较复杂的类型,复制构造函数和析构函数可能带来较大的开销。使用引用参数,便不会调用复制构造函数和析构函数
template<class T>
T abc(T &a,T &b,T &c) {
return a + b * c;
}
常量引用参数
常量引用下指明的引用参数不能被函数修改
template<class T>
T abc(const T &a,const T &b,const T &c) {
return a + b * c;
}
使用const来指明函数不可修改的引用参数
综上可以得到更通用的写法:
template<class Ta,class Tb,class Tc>
Ta abc(const Ta &a,const Tb &b,const Tc &c) {
return a + b * c;
}
返回值
一个函数可以返回一个值、一个引用或一个常量引用,在上述例子中,返回的对象被复制到调用环境中,函数所计算出来的表达式结果被存储在一个局部的临时变量中,当函数结束时,当函数结束时,这个临时变量所占用的空间将被释放,为了不丢失这个值,在释放空间之前,要把这个值从临时变量复制到调用该函数的环境中去。但如果给函数返回类型增加一个后缀&,便指定了一个引用返回:
T& mystery(int i,T &z)
使用语句return z返回,这种形式不会将z的值复制到返回环境中,当函数结束时,形参i以及所有的局部变量的空间都被释放掉,z是对一个实参的引用,所以不受影响
重载函数
一个函数的签名,是由这个函数的形参类型及其个数确定的。定义多个同名函数的机制叫函数重载,将函数调用语句中的签名与函数定义中的签名进行匹配,编译器就可以确定哪一个重载函数被调用
float abc(float a,float b,float c) {
return a * b + c;
}
int abc(int a,int b,int c) {
return a * b + c;
}
异常
异常是表示程序出现错误的信息
抛出异常
可以对一些异常情况进行检查,当查出一个异常就抛出,例如下方程序,当三个参数都大于0时才计算表达式的值,其他情况都抛出异常
int abc(int a,int b,int c) {
if (a <= 0 || b <= 0 || c <= 0) {
throw "All parameters should be > 0";
}
return a + b * c;
}
程序可能抛出的异常有很多类型,C++具有一个异常类的层次结构,类exception是根,标准C++函数通过抛出一种异常来表明异常的出现,而这种异常是从基类exception派生的类型
处理异常
一段代码抛出的异常由包含这段代码的try语句块来处理
int abc(int a,int b,int c) {
if (a <= 0 || b <= 0 || c <= 0) {
throw "All parameters should be > 0";
}
return a + b * c;
}
int main(void) {
try {
cout << abc(2,0,4) << endl;
} catch (char const* e) {
cout << "The parameters to abc were 2,0 and 4" << endl;
cout << "An exception has been thrown" << endl;
cout << e << endl;
}
return 0;
}
紧跟在try块之后的catch块,每一个catch块都有一个参数,参数的类型决定了这个catch块要捕获的异常类
输出:
The parameters to abc were 2,0 and 4
An exception has been thrown
All parameters should be > 0
可以有多个catch块,如果有一个异常被抛出,那么try块的正常运行停止,程序进入第一个能捕获到这种异常类型的catch块,其他catch块将被忽略,如果没有一个catch块能够与抛出的异常类型相对应,那么异常就会跨越嵌入在try块里的层次结构,寻找在层次结构中能够处理这个异常的第一个catch块,如果依然没有,那么程序非正常停止
动态存储空间分配
操作符new
new用于进行动态存储分配或运行时存储分配,其值是一个指针,指向所分配空间,例如给一个整数动态分配存储空间,并复制为10:
int *y = new int(10);
等价于:
int *y = new int;
*y = 10;
操作符new分配了一块能够存储一个整数的空间,并将该空间的指针赋给y,y是对整数指针的引用,而*y是对整数本身的引用
一维数组
动态存储分配的方式创建一维数组,如下创建一个长度为n的一维浮点数组
float *x = new float[n];
操作符new为n个浮点数分配了存储空间,并返回第一个浮点数空间的指针
异常处理
如果计算机没有足够的内存可以分配,那么new就会抛出一个bad_alloc类型的异常,可以利用try-catch来捕获:
int main(void) {
int n = 10;
float *x;
try {
x = new float[n];
} catch (bad_alloc e) {
cerr << "Out of Memory" << endl;
::exit(1);
}
return 0;
}
二维数组
使用动态分配创建一个二维数组
template <class T>
void make2dArray(T** &x,int numberOfRows,int numberOfColumns) {
x = new T*[numberOfColumns];
for (int i=0;i<numberOfRows;i++) {
x[i] = new int [numberOfColumns];
}
}
如果数组的列数在编译时是未知的,那么不可能仅调用一次new就能创建这个二维数组,要构造这样的二维数组,可以将其看作是油若干行所构成的结构,每一行用new来创建一个一维数组
释放内存空间:
template<class T>
void delete2dArray(T** &x,int numberOfRows) {
for (int i=0;i<numberOfRows;i++) {
delete[] x[i];
}
delete[] x;
x = NULL;
}
分两步释放二维数组空间,首先释放为每一行所分配的空间,然后释放为行指针所分配的空间,将x置NULL,防止用户继续访问已被释放的空间
C++核心知识回顾(函数&参数、异常、动态分配)的更多相关文章
- Docker 核心知识回顾
Docker 核心知识回顾 最近公司为了提高项目治理能力.提升开发效率,将之前的CICD项目扩展成devops进行项目管理.开发人员需要对自己的负责的项目进行流水线的部署,包括写Dockerfile ...
- [C#] C# 知识回顾 - 学会处理异常
学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...
- [C#] C# 知识回顾 - 学会使用异常
学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...
- Java核心知识体系3:异常机制详解
1 什么是异常 异常是指程序在运行过程中发生的,由于外部问题导致的运行异常事件,如:文件找不到.网络连接失败.空指针.非法参数等. 异常是一个事件,它发生在程序运行期间,且中断程序的运行. Java ...
- Python 编程核心知识体系-函数(二)
函数
- python---基础知识回顾(二)(闭包函数和装饰器)
一.闭包函数: 闭包函数: 1.在一个外函数中定义了一个内函数 2.内函数里运用了外函数的临时变量,而不是全局变量 3.并且外函数的返回值是内函数的引用.(函数名,内存块地址,函数名指针..) 正确形 ...
- c++11-17 模板核心知识(十二)—— 模板的模板参数 Template Template Parameters
概念 举例 模板的模板参数的参数匹配 Template Template Argument Matching 解决办法一 解决办法二 概念 一个模板的参数是模板类型. 举例 在c++11-17 模板核 ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- [C#] C# 知识回顾 - 异常介绍
异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...
- $Django 路飞之小知识回顾,Vue之样式element-ui,Vue绑定图片--mounted页面挂载--路由携带参数
一 小知识回顾 1 级联删除问题 2 一张表关联多个表,比如有manytomanyfileds forignkey,基于对象查询存在的问题:反向查询的时候 表名小写_set.all()不知是哪个字段 ...
随机推荐
- Docker部署NextCloud
docker run -d -p 80:80 nextcloud 数据库可以选Mysql或者Pg 下载客户端 https://nextcloud.com/
- CH573 CH579 CH582程序烧录讲解
WCH的蓝牙芯片CH57x/CH58x系类大部分是支持串口烧录.USB烧录和LINK烧录的,除了一些特殊的封装,如571K,它引脚较少,只支持串口免按键烧录. 仿真下载:ARM内核的CH579支持Jl ...
- 从XXE漏洞修复引起Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD说到SPI机制
引子 在使用Fortify扫描时代码报XML External Entity Injection,此漏洞为xml实体注入漏洞,XXE攻击可利用在处理时动态构建文档的 XML 功能.修复方案也包含了增 ...
- 【Python】validator进行数据校验
https://pypi.org/project/validator.py/ 校验参数必要性 from validator import Required, In, InstanceOf, Lengt ...
- python requests 上传文件_python3使用requests上传文件,content-type踩的坑
通常提交普通表单时,requests的post方法可以指定headers,所以我在使用requests模拟上传文件行为时,直接按照下面的方式写了: 然后服务器就报出了找不到分隔符Invalid mul ...
- c++中文编码格式
c++程序中涉及到中文字符的输入输出以及其他操作经常会出现乱码.乱码主要是由于程序的源文件编码.可执行文件编码以及程序运行环境的编码不匹配导致.比如,c++源程序文件编码为GB18030, 在源程序中 ...
- 生产环境Java应用服务内存泄漏分析与解决
有个生产环境CRM业务应用服务,情况有些奇怪,监控数据显示内存异常.内存使用率99.%多.通过生产监控看板发现,CRM内存超配或内存泄漏的现象,下面分析一下这个问题过程记录. 服务器配置情况: 生产服 ...
- Android笔记--SQL
SQL基本语法 基本语法在Python和Java那里都已经重复过了,这里就不再重复了 SQLiteDatabase--SQLite的数据库管理类 主要分为以下3类: 管理类 相关实现: 事务类 数据库 ...
- Spring--案例:测试业务层接口万次执行效率
案例来袭 这样,并不能够分辨出哪个的效率是哪个 可以利用pjp进行这样的操作: 结果:
- 声网传输层协议 AUT 的总结与展望丨Dev for Dev 专栏
本文为「Dev for Dev 专栏」系列内容,作者为声网大后端传输协议负责人 夏天. 针对实时互动应用对网络传输带来的新需求和新挑战,声网通过将实时互动中的应用层业务需求与传输策略的分层和解耦,于 ...