处理可能出现异常的方法
- 调用abort()或exit()结束程序
- 返回错误码
- 异常机制:1.使用try块执行可能出现异常的代码段 2.throw引发异常 3.catch捕获并处理对应情况
throw机制
若throw引发异常后,匹配对应catch。而后不是将控制权返回调用程序,而是引导程序沿着函数调用序列后退,直到找到try块中的函数
若没有throw出异常,则catch被跳过.
一般而言后退多步,再在main()中寻找与引发异常类型匹配的处理程序作处理。
通常用对象作为异常类型处理
好处是:直接根据类型区分异常,另外对象可以携带信息确定原因,catch根据信息来执行对应的操作
堆栈解退(unwinding the stack)
假设函数出现异常,而不是正确返回而终止。程序释放堆栈中的内存,但不会在释放堆栈的第一个返回地址后停止,而是继续释放堆栈,直到找到位于try块的返回地质。程序进行堆栈解退以回到能够捕获异常的地方时,将释放堆栈中的自动存储型变量。
文件IO
1 |
|
下面程序为harmony mean的除0错误,抛出const char *类型,匹配输出错误信息的代码。一般抛出错误类型通常为类。
1 |
|
throw-catch机制和函数参数以及函数返回机制的区别
1.函数控制权返回到调用函数的函数,throw语句控制权向上返回到第一个包含能够捕获相应异常的try-catch组合
2.引发异常时,编译器总是创建一个临时拷贝,彻底避免了函数机制指向不存在的临时变量的问题。
3.经常可见catch(problem & p),使用了引用,主要是针对通过继承关联起来的异常类型;此时使用基类引用即可执行派生类对象。此时层次结构最下面的异常类的catch语句应当放在最前面。
catch (…)表示捕获任何异常
异常处理的注意事项
1.使用异常,应在设计程序时就加入,而不是以后才添加。
2.使用异常会增加程序代码,降低程序运行速度。
3.异常规范不适用于模板,异常和动态内存分配不能总是协同工作
因此,虽然异常处理对于某些项目极为重要,但也会增加编程的工作量、增大程序以及降低程序的速度。另外编译器对异常的支持以及用户的经验还没有达到成熟的程度,应有节制地使用这一特性。
如无堆栈解退,则会出现内存泄漏,如下
1 | void test(int n) |
throw了,则delete[]被忽略,ar指针消失了,内存块未释放且不可访问。
RTTI(RunTime Type Identification)
三个支持RTTI的元素:
- dynamic_cast操作符将基类指针生成派生指针:回答是否可以安全将对象的地址赋给特定类型的指针?如可,返回对象地址;否则,返回空指针。这对比“指向哪个类型的对象”,这更通用且有用。
- typeid操作符返回对象的类型
- type_info存储特定类型的信息
注意:RTTI只适用于包含虚函数的类
与通用转换机制相比,dynamic_cast、static_cast、const_cast、reinterpret_cast提供了更安全和明确的类型转换。
STL
通用编程技术,迭代器概念。
操作复杂度:固定时间、线性时间、随机时间
线性容器以及联合容器(set、map、multiset、multimap)
()函数符functor的概念,STL使用模板让for_each原型看上去像
1 | template<class InputIterator, class Function> |
STL算法库
分为四大类
- 非修改式序列操作
- 修改式序列操作
- 排序和相关操作
- 通用数字运算
就地算法:在原始数据位置上操作;复制算法:在新的位置操作
IO
cout不会截断数据,会尽量全部打印内容。
1 | cout.width(int n); // 单次有效 |