一.异常
1.概念
异常:程序运行时出现的问题。如果编译通过,说明代码是逻辑问题,不是语法问题。
2.异常处理
处理方式分为抛出异常和捕获异常。
抛出异常:使用throw抛出任意类型异常,如果不处理则会使程序停止。
#include <iostream>
using namespace std;
double division(double a,double b){
if(b==0){
throw 'e'; //抛出char类型的异常
}
return a/b;
}
int main()
{
double a=3.5;
double b=2;
cout<<division(a,b)<<endl;
b=0;
cout<<division(a,b)<<endl;
cout<<"________"<<endl;
}
捕获异常:使用try-catch代码块捕获异常,try代码块表示可能出现异常的代码,catch快表示如果try块中出现异常,则与catch捕获的异常类型进行匹配,匹配成功后执行catch块代码。
3.捕获自定义类的异常
捕获任意类型,不一定非得是字符型
4.将自定义类继承标准异常
1.没加入标准异常库时,程序运行只会抛出异常类型,具体错误信息不打印
2.自定义的类加入标准异常库,抛出异常会有具体错误信息,
需要加入#include<stdexcept>头文件,公共继承exception异常基类,重写what()方法
class DivisionByZero:public exception{ //继承标准异常类
public:
const char * what() const throw(){
return "除0错误了。。";
}
5.拓展捕获
1.多重捕获:在try代码块后加上多个catch块。
2.捕获基类异常:catch代码块为catch(const exception){。。。。。}
目的:提高异常捕获的概率
2.智能指针
概念:用于管理堆内存对象的生命周期,能使堆内存对象自动回收,当智能指针对象的生命周期结束后,会在析构函数里释放管理的堆内存对象的内存空间,从而避免内存泄露。
//第一种auto_ptr的创建方式 对象的指针做参数
Test * t3=new Test("t3指向的堆内存对象");
auto_ptr<Test> ap1(t3);
cout<<ap1.get()<<" "<<t3<<endl; //0x761908 0x761908
//第二种创建方式 匿名对象做参数
auto_ptr<Test> ap2(new Test("ap2管理的堆内存对象"));
cout<<ap2.get()<<endl;
get()方法,可以得到管理对象的首地址
1.2 reset方法
放弃一个对象的管理权,把该对象的内存释放
Test * tb=new Test("B");
ap1.reset(tb);
1.3 release
只是释放管理权,但没有释放空间
Test * ta=new Test("A");
auto_ptr<Test> ap1(ta);
//release只是释放管理权,但没有释放空间
//名为“ta“对象指针指向内存还是需要手动delete销毁
ap1.release();
1.4.auto_ptr的缺陷
复制语言(拷贝和赋值)会发生控制权的转移,有时不是主观的操作,造成 错误
Test * tb=new Test("B");
auto_ptr<Test> ap1(tb);
auto_ptr<Test> ap2(ap1);
auto_ptr<Test> ap3=ap2;
内部屏蔽了复制语义(拷贝,赋值) 也就这些操作不会发生控制权的转移。
用move方法还是可以转移控制权,只是提高了转移的门槛
unique_ptr<Test> ap2(move(ap1));
unique_ptr<Test> ap3=move(ap2);