基于C的C++学习day6

异常处理

1.异常概念

异常运行期间发生的错误。编译的时候没有错,语法是正确的,但是逻辑出现了问题

常见异常如 数组越界, 除0报错,申请内存空间出错。

序出现错误,如果没有处理,就会停止运行

 

#include <iostream>
#include <list>
using namespace std;
int main()
{
  string s="abc"; //下标到2
  s.at(3);
  cout<<"main方法"<<endl;

}

 

2.处理异常的方式:

解决异常:

处理了 try,,,catch

抛出异常 throw

exception是所有异常的基类。

#include <iostream>
#include <list>
using namespace std;

int main()
{
  string s="abc"; //下标到2
  try{
      s.at(3);
      cout<<"hello"<<endl; //上一行出现错误,就不会运行输出
      
  }catch(exception e){
     //解决办法
      cout<<"问题已解决"<<endl;
  }

  cout<<"main方法"<<endl;

}

c++标准异常库

 

 

#include <iostream>
using namespace std;

int main()
{
    double a=2.5,b=0;
    string name="zhangsan";

    try{
        if(b==0)
            throw -1;
        cout<<a/b<<endl; //inf
    }  
    catch(int e){
        cout<<"没事可以通过"<<endl;
    }
}

catch可以捕获任意类型的异常。如下发可以捕获throw的int 和 char类型异常

#include <iostream>
using namespace std;

int main()
{
    double a=2.5,b=1;
    string name="zhangsan";
    string str;
    try{
        if(b==0)
            throw -1;
        if("zhangsan"==name)
           throw 'e';

        cout<<a/b<<endl; //inf
    }
    catch(int e){
        cout<<"没事可以通过"<<endl;
    }
    catch(char e){
        cout<<"张三上线"<<endl;
    }
}

继承异常基类。

#include <iostream>
using namespace std;
class MyException:public exception{ //自己创建的类 作为异常类
public:
    const char * what() const throw(){
        return "除数不能为0";
    }

};
double division(const int & a,const int & b){
    if(b==0)
        throw MyException();
    return a/b;

}
int main()
{
    double n=1.5,m=0;
    try{
       division(n,m);
    }catch(MyException ess){
        cout<<ess.what()<<endl;
    }
    cout<<"-----------"<<endl;

}

4.多重捕获

为了增加错误捕获的概率,catch捕获的异常可以写多个.

直接用基类except都可以捕获到错误,但看不出具体什么错误。

可以用多重捕获,增加异常可以正常捕获的概率。但如果都没有catch捕获到,程序还是会停止。

#include <stdexcept> //C++异常处理标准头文件

#include <iostream>
#include <stdexcept> //异常处理头文件
using namespace std;

int main()
{
    string s="abc";
    try{
       s.at(4);
    }catch(const out_of_range e){
        cout<<e.what();
    }
    catch(exception e){
        cout<<e.what();
    }

}

exception只能处理已经定义的异常。 catch(...)可以处理任意的

注意事项:把具体的异常类捕获放在前面,基类放在后面

#include <iostream>
#include <stdexcept> //异常处理头文件
using namespace std;

int main()
{
    string s="abc";
    try{
       throw("hello");
       cout<<s.at(2)<<endl;
    }catch(const out_of_range e){
        cout<<e.what()<<endl;
    }
    catch(exception e){
        cout<<e.what();
    }
    catch(...){
        cout<<"。。。"<<endl;
    }
    cout<<"main_end"<<endl;

}

智能指针

new出来的对象需要手动销毁,如果忘记销毁就会造成内存泄漏。c++98之后引入了智能指针。是堆内存对象自动回收

智能指针是也是类模板,是在栈上创建对象。new()出来的对象指针在栈上。智能指针对象可以对这些普通指针进行管理。当智能指针对象的生命周期结束。就会在析构函数中释放掉管理对象的内存,防止内存泄漏。

auto_ptr 现在不推荐使用

unique_ptr 唯一指针

shared_ptr 共享指针

weak_ptr 虚指针tt

auto_pt

auto_ptr<Test> ptr(t) 意思:

<Test>管理的类的名字

ptr智能智能名字

t 需要传入内存对象地址

#include <iostream>
#include <memory>
using namespace std;
class Test{
private:
    string str;
public:
    Test(string s):str(s){
        cout<<str<<"创建了"<<endl;
    }
    ~Test(){
        cout<<str<<"销毁了"<<endl;
    }
};
int main()
{

    Test * t=new Test("A");
    auto_ptr<Test> ptr(t);
 
    //推荐下面这种
    auto_ptr<Test> ptr2(new Test("B"));

}

问题:在复制语义中出现控制权转移问题 如赋值。拷贝函数

#include <iostream>
#include <memory>
using namespace std;
class Test{
private:
    string str;
public:
    Test(string s):str(s){
        cout<<str<<"创建了"<<endl;
    }
    ~Test(){
        cout<<str<<"销毁了"<<endl;
    }
    void show(){
        cout<<"成员值:"<<str<<endl;
    }
};
int main()
{

    Test * t=new Test("A");
    auto_ptr<Test> ptr1(t);
    //get()方法可以得到对象地址
    cout<<ptr1.get()<<" "<<t<<endl; //0x12417d8 0x12417d8

    //推荐下面这种
    auto_ptr<Test> ptr2(new Test("B"));
    ptr2.get()->show(); //B

    //重写管理新的对象 会销毁原来的对象
    ptr2.reset(new Test("C"));

    //不能用普通指针赋值
    auto_ptr<Test> ptr3=ptr1; //拷贝
    auto_ptr<Test> ptr4(ptr2); //显示拷贝
    cout<<ptr1.get()<<endl; //0
    cout<<ptr2.get()<<endl; //0
    cout<<ptr3.get()<<endl; //0xeb17d8
    cout<<ptr4.get()<<endl; //0xeb2a08

}

unique_ptr(掌握)

#include <iostream>
#include <memory>
using namespace std;
class Test{
private:
    string str;
public:
    Test(string s):str(s){
        cout<<str<<"创建了"<<endl;
    }
    ~Test(){
        cout<<str<<"销毁了"<<endl;
    }
    void show(){
        cout<<"成员值:"<<str<<endl;
    }
};
int main()
{

    Test * t=new Test("A");
    unique_ptr<Test> ptr1(t);
    //get()方法可以得到对象地址
    cout<<ptr1.get()<<" "<<t<<endl; //0x12417d8 0x12417d8

    //推荐下面这种
    unique_ptr<Test> ptr2(new Test("B"));
    ptr2.get()->show(); //B

    //重写管理新的对象 会销毁原来的对象
    ptr2.reset(new Test("C"));

    //不能用普通指针直接赋值
//    unique_ptr<Test> ptr3=ptr1; //不允许隐身拷贝
//    unique_ptr<Test> ptr4(ptr2); //不允许显示拷贝
//    unique_ptr<Test> ptr5;
//    ptr5=ptr1;                 //不允许赋值
    cout<<ptr1.get()<<endl; //0
    cout<<ptr2.get()<<endl; //0

}

shared_ptr(掌握)

#include <iostream>
#include <memory>
using namespace std;
class Test{
private:
    string str;
public:
    Test(string s):str(s){
        cout<<str<<"创建了"<<endl;
    }
    ~Test(){
        cout<<str<<"销毁了"<<endl;
    }
    void show(){
        cout<<"成员值:"<<str<<endl;
    }
};
int main()
{

    Test * t=new Test("A");
    shared_ptr<Test> ptr2;
    {
    shared_ptr<Test> ptr1(t);
     ptr2=ptr1; //**
     cout<<"1):"<<ptr1.use_count()<<endl;
    //不能用普通指针赋值
    shared_ptr<Test> ptr3=ptr1;
    cout<<"2):"<<ptr1.use_count()<<" "<<ptr3.use_count()<<endl;

    shared_ptr<Test> ptr4(ptr1);
    cout<<"3):"<<ptr1.use_count()<<" "<<ptr3.use_count()
       <<" "<<ptr4.use_count()<<endl;
    shared_ptr<Test> ptr5;
    ptr5=ptr1;
     cout<<"3):"<<ptr1.use_count()<<" "<<ptr3.use_count()<<" "
        <<ptr4.use_count()<<" "<<ptr5.use_count()<<endl;
     ptr5.reset(); //ptr5释放了自己的管理权。但资源还被其他智能指针共享
     cout<<"end):"<<ptr1.use_count()<<" "<<ptr3.use_count()<<" "
        <<ptr4.use_count()<<" "<<ptr5.use_count()<<endl;
   }
   cout<<ptr2.use_count()<<endl;
   cout<<"------------";

}
/*
A创建了
1):2
2):3 3
3):4 4 4
3):5 5 5 5
end):4 4 4 0
1
------------A销毁了
*/

shared_ptr<Test> ptr9=make_shared<Test>("B");

特点:性能更好 更加安全

weak_ptr

不实际控制对象生命周期,也就不会增减use_count()

协助shared_ptrl来使用的

解决shared_ptrl的循环引用的问题

#include <iostream>
#include <memory>
using namespace std;
class Test{
private:
    string str;
public:
    Test(string s):str(s){
        cout<<str<<"创建了"<<endl;
    }
    ~Test(){
        cout<<str<<"销毁了"<<endl;
    }
    void show(){
        cout<<"成员值:"<<str<<endl;
    }
};
int main()
{
//    weak_ptr<Test> ptr9=make_shared<Test>("B");
    shared_ptr<Test> ptr1(new Test("A"));
    weak_ptr<Test> ptr2;
    {

     ptr2=ptr1; //**
     cout<<"1):"<<ptr1.use_count()<<endl;
    //不能用普通指针赋值
    weak_ptr<Test> ptr3=ptr1;
    cout<<"2):"<<ptr1.use_count()<<" "<<ptr3.use_count()<<endl;

    weak_ptr<Test> ptr4(ptr1);
    cout<<"3):"<<ptr1.use_count()<<" "<<ptr3.use_count()
       <<" "<<ptr4.use_count()<<endl;
    weak_ptr<Test> ptr5;
    ptr5=ptr1;
     cout<<"3):"<<ptr1.use_count()<<" "<<ptr3.use_count()<<" "
        <<ptr4.use_count()<<" "<<ptr5.use_count()<<endl;
     ptr5.reset(); 
      cout<<"end):"<<ptr1.use_count()<<" "<<ptr3.use_count()<<" "
        <<ptr4.use_count()<<" "<<ptr5.use_count()<<endl;
   }
   cout<<ptr2.use_count()<<endl;
   cout<<"------------";

}

nullptr

#define NULL 0

c++11中用来代替NULL

#include <iostream>
#include <memory>
using namespace std;
void func(int){
    cout<<"n"<<endl;
}
void func(char *){
    cout<<"char *"<<endl;
}
int main()
{
    char *c=NULL;
    func(c); //char *

    func(NULL); //n

    func(nullptr);//char *
}

其他内容:

类型推导

auto不能用于参数。也不能支持数组和表达式

#include <iostream>
using namespace std;

int main()
{
    auto i=6;
    cout<<i<<endl;

    auto i2=new auto(18);
    cout<<*i2<<endl;

    int * i3=new int(18);
    cout<<*i3<<endl;
}

进制输出

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    //默认10进制
   cout<<showbase; //没有括号
   cout<<oct; //8进制
   cout<<11<<endl; //013
   cout<<hex<<15<<endl; //0xf
   cout<<dec<<6<<endl; //6
   cout<<noshowbase;
}

设置场宽

#include <iomanip>

#include <iostream>
#include <iomanip>
using namespace std;
int main()3
{
    cout<<setw(5)<<7<<endl;
    cout<<"#########"<<endl;
     cout<<setw(5)<<setfill('*')<<7<<endl; //默认右对齐
}

字符串流

#include <iostream>
#include <sstream>
using namespace std;
int main()
{
    //int到string
    stringstream ss;
    int i=1234;
    ss<<i;
    string s=ss.str();
    cout<<s<<endl;
    s.append("hello");
    cout<<s<<endl;

    //string到int

    string s2="1234567";
    istringstream iss(s2);
    iss>>i;
    cout<<i<<endl;
    cout<<++i<<endl;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值