复习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++核心知识回顾(函数&参数、异常、动态分配)的更多相关文章

  1. Docker 核心知识回顾

    Docker 核心知识回顾 最近公司为了提高项目治理能力.提升开发效率,将之前的CICD项目扩展成devops进行项目管理.开发人员需要对自己的负责的项目进行流水线的部署,包括写Dockerfile ...

  2. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  3. [C#] C# 知识回顾 - 学会使用异常

    学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...

  4. Java核心知识体系3:异常机制详解

    1 什么是异常 异常是指程序在运行过程中发生的,由于外部问题导致的运行异常事件,如:文件找不到.网络连接失败.空指针.非法参数等. 异常是一个事件,它发生在程序运行期间,且中断程序的运行. Java ...

  5. Python 编程核心知识体系-函数(二)

    函数

  6. python---基础知识回顾(二)(闭包函数和装饰器)

    一.闭包函数: 闭包函数: 1.在一个外函数中定义了一个内函数 2.内函数里运用了外函数的临时变量,而不是全局变量 3.并且外函数的返回值是内函数的引用.(函数名,内存块地址,函数名指针..) 正确形 ...

  7. c++11-17 模板核心知识(十二)—— 模板的模板参数 Template Template Parameters

    概念 举例 模板的模板参数的参数匹配 Template Template Argument Matching 解决办法一 解决办法二 概念 一个模板的参数是模板类型. 举例 在c++11-17 模板核 ...

  8. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  9. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

  10. $Django 路飞之小知识回顾,Vue之样式element-ui,Vue绑定图片--mounted页面挂载--路由携带参数

    一 小知识回顾 1 级联删除问题 2 一张表关联多个表,比如有manytomanyfileds forignkey,基于对象查询存在的问题:反向查询的时候  表名小写_set.all()不知是哪个字段 ...

随机推荐

  1. RabbitMQ安装失败 地址提示错误

    最后设置为: D:\RabbitMQ\rabbitmq_server-3.7.10-rc.3\sbin>set ERLANG_HOME=D:\Erlang\erl10.2

  2. vue使用keepalive缓存上级页面

    参考: vue单页应用前进刷新后退不刷新方案探讨 vue,vue-router实现浏览器返回不刷新页面 vue 怎么处理当this.$router.go(-1)时,判断返回指定页面设置指定页面的kee ...

  3. flask-script的简单使用

    1.Flask-Script介绍Flask-Script的作用是可以通过命令行的形式来操作Flask.Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定 ...

  4. Node.js+Vue.js开发王者荣耀手机端官网

    一.项目初始 1.工具安装和环境搭建 node.js.npm.mongodb 编辑器:VScode 2.项目初始化 项目分为三个部分,分别是移动端界面.后台管理界面和node.js开发的整体的服务端 ...

  5. QT网络编程【二】【Socket】

    1.QT中添加socket 库的相关操作 2.正常c++11 VS2019使用socket库的操作 3.winsock2 与 sys/socket.h的区别? 4.WinSock2 的基本操作? 详细 ...

  6. MySQL代替in之临时表

    如果我们正常的使用IN去查询 SELECT * FROM a JOIN b ON a.id = b.id WHERE b.tag_id IN (1,2,3,4,5,6) 这种因为in里面的参数是连续的 ...

  7. input_subsys 输入子系统框架分析

    在linux内核中 已做好各类驱动的框架,驱动程序也属于内核的一部分,我们可以在原有的驱动上修改,来匹配我们自已的硬件,也可以自已编写符合内核驱动框架的驱动程序.出于学习的目的,便于更好的理解各类驱动 ...

  8. verilog 概念版

    一.MCU芯片的定义 MCU芯片是指微控制单元(MicrocontrollerUnit:MCU),又称单片微型计算机或者单片机,是把中央处理器的频率与规格做适当缩减,并将内存.计数器.USB.A/D转 ...

  9. 华大单片机HC32L13X软件设计时候要注意的事项

    1.系统启动时默认设置主频为内部4MHz; 2.调试超低功耗程序或者把SWD端口复用为GPIO功能都会把芯片的SWD功能关掉,仿真器将会与芯片失去连接,建议在main函数开始后加上1到2秒的延时,仿真 ...

  10. 织梦(DedeCMS)安全方案

    一.织梦(DedeCMS)介绍 织梦(DedeCMS)作为国内龙头CMS系统之一,因其系统结构科学合理,操作使用简单,拥有海量用户.和其他CMS一样,安全漏洞也是其无法避免的问题.虽然官方不断发布补丁 ...