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()不知是哪个字段 ...
随机推荐
- php json_encode使用中文不转码
PHP转JSON,中文会被转码成unicode,使用常量JSON_UNESCAPED_UNICODE可以使中文原样输入 echo json_encode("中文"); //Outp ...
- FileLocator Pro注册机
- Q:带宽检测 iperf工具
一.下载 iperf的下载地址为:https://iperf.fr/iperf-download.php,选择相应的版本 linux安装 rpm -qa|grep -i rperf rpm -ivh ...
- C语言基础编程题
//1.ASCII码值 ->相应字符 #include <stdio.h> int main() { int asc; scanf("%d",&asc); ...
- HOOK大法
// 请求头hook 测试网站同花顺 OK var header_old = window.XMLHttpRequest.prototype.setRequestHeader;window.XMLHt ...
- 【node打包缺包】Error: Can't walk dependency graph: Cannot find module 'jquery' from
问题: 在使用node打包时,终端报错提示Error: Can't walk dependency graph: Cannot find module 'jquery' from/.../ 这个提示缺 ...
- c语言数据结构 树的基本操作
树的基本操作有创建,插入,删除,以及各种遍历的应用,如:利用后序遍历求高度,利用前序遍历求层数的结点 基本算法思路:创建二叉树函数参数必须接受二级指针!如果使用同级指针,无法返回创建后的结果,利用递归 ...
- Keil MDK5编译时出现错误:error: L6002U: Could not open file …\obj\main.o: No such file or directory,
原因:电脑系统用户名中存在中文字符 解决:用户环境变量,找到变量 TEMP 和 TMP,将变量值中的"%USERPROFILE%"使用"C:\user\default&q ...
- Appium--滑动屏幕、不常用API
1.滑动屏幕api #滑动屏幕 size = driver.get_window_size() #获取屏幕大小 width = size.get('width') #宽 height = size.g ...
- pip第三方库安装失败原因及解决办法
pip安装三方库失败原因及解决方法 提示:WARNING: You are using pip version 20.2.3, however version 20.2.4 is available. ...