首页 > 编程语言 >C++实战笔记(三)异常处理

C++实战笔记(三)异常处理

时间:2023-01-21 12:31:16浏览次数:53  
标签:实战 exception int 笔记 next C++ catch 异常



tags: C++ Interview

写在前面

简单总结一下C++异常处理部分(Exception).

异常只是C++为了处理错误提出的一种解决方案, 并不是唯一的一种.

异常处理

特点

  1. 异常处理的流程完全独立
  2. 异常不能被忽略, 必须被处理
  3. 异常可以用在错误码无法使用的场合中

错误类型的继承关系

总结自CPP Primer第五版














Exception


runtime_error


bad_cast


bad_alloc


logic_error


range_error


overflow_error


underflow_error


invalid_argument


length_error


out_of_range


domain_error


判断什么时候使用异常

  1. 不允许被忽略的错误
  2. 极少数情况下才会发生的错误
  3. 严重影响代码的正常运行流程, 很难恢复到正常状态的错误
  4. 无法本地处理. 必须穿透"调用栈", 传递到上层才能被处理的错误.

例子:

  • 构造函数, 内部初始化失败, 则后面的逻辑也无法进行, 这时候可以用异常处理.
  • 读写文件, 使用异常判断文件权限问题的错误
  • socket编程, 不要使用异常(因为经常出现网络问题, 使用异常降低性能)

代码示例

继承runtime_error

class my_exception : public std::runtime_error {
public:
using this_type = my_exception;
using super_type = std::runtime_error;

public:
my_exception(const char* msg) : super_type(msg) {}
/* my_exception() = default; */
~my_exception() = default;

private:
int code = 0;
};

封装throw

[[noreturn]] void raise(const char* msg) { throw my_exception(msg); }

catch语句块

异常只能按照catch块在代码中的 顺序依次匹配, 而不是去找最佳匹配

建议: 只使用一个catch块, 例如:

try {
raise("error occuerd");
} catch (const exception& e) {
cout << e.what() << endl; // what()是exception类的虚函数
}

function-try

void fun()
try {
...
} catch (...) {
...
}

仍然用上面的例子:

void t2() try { raise("error occuerd"); } catch (const exception& e) {
cout << e.what() << endl;
}

优点:

  1. 捕获函数执行过程中所有可能的异常
  2. 少了一层缩进, 逻辑清晰

使用noexcept

这个关键字专门用来修饰函数, 用来告诉编译器被修饰的函数不会抛出异常.

void func_noexcept() noexcept { cout << "noexcept\n"; }

只是一个声明, 就算函数体内部抛出了异常, 也是可以的.

void func_noexcept() noexcept {
cout << "noexcept\n";
throw(1);
}
// output:
//terminate called after throwing an instance of 'int'

特殊异常的处理方法

下面介绍一些实际使用中用到的C++异常, 例如在力扣中使用异常来避免使用判断语句(虽然理想很丰满), 以及

数组越界异常

先来看这样一道题:

​剑指 Offer 64. 求1+2+…+n - 力扣(LeetCode)​​;

使用Python的话, 可以这样写:

class Solution:
def sumNums(self, n: int) -> int:
try:
a = [0]
return a[n - 1] + n
except Exception:
return n + self.sumNums(n - 1)

那么神通广大的C++可以这样做吗? 答案是:No…(并且就算这样可以也不是最优解)

来看看如果用C++捕获异常的情况:

class Solution {
public:
int sumNums(int n) {
int a[1]{0};
try {
if (n - 1 >= 1) throw 1;
return a[n - 1] + n;
} catch (int) { return n + sumNums(n - 1); }
}
};

没错, 必须手动判断然后通过​​throw​​抛出异常, 是不是很逆天… 并不智能.

空指针异常

这里是另一道力扣题:

​141. 环形链表 - 力扣(LeetCode)​​;

当然快慢指针是最快的方法, 不过判断指针的异常情况也可以, 例如Python:

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
s=f=head
while 1:
try:
s=s.next
f=f.next.next
except Exception as e:
return False
if s==f:
return True

但是, 用C++来直接捕获空指针异常就是不可能的, 只能手动加判断然后抛出异常:

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
auto fast = head, slow = head;
while (1) {
try {
if (!fast || !fast->next) throw 1;
fast = fast->next->next;
slow = slow->next;
} catch (int) { return false; }
if (fast == slow) return true;
}
}
};

不过, 这样倒是也好, 不会惯坏C++程序员, 像这种错误会引起​​core dump​​, 还是尽早处理了好, 别等到实际运行的时候才去处理.

​c++ - How to catch the null pointer exception? - Stack Overflow​​;


标签:实战,exception,int,笔记,next,C++,catch,异常
From: https://blog.51cto.com/u_15366127/6021102

相关文章

  • 每刻和金蝶云星空接口打通对接实战
    每刻和金蝶云星空接口打通对接实战接通系统:每刻3000+中大型企业在用,新一代业财税一体化解决方案提供商。旗下拥有每刻报销、每刻档案、每刻云票、每刻财务共享云平台等......
  • c++ return
    return本是上是一个拷贝过程,不过是右值拷贝,也就是无标记变量的拷贝。不管是返回指针还是返回值,return首先将要return的值存到eax寄存器中,回到父函数再将返回的值赋给变量......
  • 关于海明码的问题(语言-c++)
    提问:   我头都大了,想了半天也没想出这个括号里面是怎么算出来的,有明白的吗,请赐教下。解答: 以下是一个C++编程实现海明码的示例:#include<iostream>#include<strin......
  • 计算几何笔记(一):点与向量
    开始之前圆周率constpi=acos(-1);浮点数的比较对实数进行浮点运算难免会出现精度误差为了控制精度,可以设置一个偏差值\(eps\)constdoubleeps=1e-5;intsgn(......
  • fabric学习笔记10
    fabric学习笔记1020201303张奕博2023.1.22测试实践1.启动网络命令:cdfabric-samples/chaincode-docker-devmode/docker-compose-fdocker-compose-simple.......
  • 读函数式编程思维笔记02_转变思维
    1. 命令式编程1.1. 按照“程序是一系列改变状态的命令”来建模的一种编程风格1.2. 传统的for循环1.2.1. 确立初始状态1.2.2. 每次迭代都执行循环体中的一系列命......
  • Foundations of Embedded IoT Systems 复习笔记 南安
    Communicationshub,border-routerorGatewaylinkslowpowerhardwaretotheoutsideworldNetworkWifi/EthernetLowPowerWideAreaNetworksLowpowerIPv6n......
  • ZYNQ学习笔记 程序固化
    ZYNQ程序的固化PS:本次实验基于zynq7010芯片,开发软件为vivado2018.3。​ zynq7010和其他的fpga板一样,日常我们开发时使用的JTAG调试下载进去的二进制文件断电后会丢失的......
  • 舞蹈链 (DLX, Dancing Links X) 算法笔记
    舞蹈链(DLX,DancingLinksX)算法精确覆盖问题在一个全集X中若干子集的集合为S,S的子集S*,满足X中的每一个元素在S*中恰好出现一次。通俗地讲,给定一个\(N\)行\(M\)......
  • 【python】Matplotlib库学习笔记
    Matplotlib是python的绘图库。以下内容主要介绍Matplotlib的子库pyplot。pyplot是常用的2D绘图模块,包含一系列绘图相关函数。plot()函数plot()函数可以用来绘制......