C++异常和断言

C++异常

  • 异常的理念看似有前途,但实际的使用效果并不好。
  • 编程社区达成的一致意见是,最好不要使用这项功能。
  • C++98引入异常规范,C++11已弃用。
    例如:我们输入1时抛出异常。
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
using namespace std;
int main() {try {//可能抛出的异常的代码int ii = 0;cout << "我是一只小小鸟?(1-傻傻鸟;2-小小鸟)";cin >> ii;if (ii == 1) throw "不好,有人说我是一只傻傻鸟";//throw抛出异常cout << "我不是一只傻傻鸟,欧耶\n";}catch (...) {//不管什么异常,都在这里处理cout << "捕捉到异常,具体不管什么异常\n";}cout << "程序继续使用....\n";//执行完try..catch...后,将继续指向程序中其他代码return 0;
}
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
using namespace std;
int main() {try {//可能抛出的异常的代码int ii = 0;cout << "我是一只小小鸟?(1-傻傻鸟;2-小小鸟)";cin >> ii;if (ii == 1) throw "不好,有人说我是一只傻傻鸟";//throw抛出const char *类型异常if (ii == 2) throw ii;//throw抛出int类型异常if (ii == 3) throw string("不好,有人说我是一只傻傻鸟.");//throw抛出string类型异常cout << "我不是一只傻傻鸟,欧耶\n";}catch (int ii) {cout << "异常的类型是int=" << ii << endl;}catch (const char* ss) {cout << "异常的类型是const char*=" << ss << endl;}catch (string str) {cout << "异常的类型是string" << str << endl;}cout << "程序继续使用....\n";//执行完try..catch...后,将继续指向程序中其他代码return 0;
}

try语句块中,如果没有发生异常,执行完try语句块中的代码后,将继续执行try语句块之后的
代码;如果发生了异常,用throw抛出异常对象,异常对象的类型决定了应该匹配到哪个catch语句
块,如果没有匹配到catch语句块,程序将调用abort()函数中止
如果try语句块中用throw抛出异常对象,并且匹配到了catch语句块,执行完catch语句块中的
代码后,将继续执行catch语句块之后的代码,不会回到try语句块中。

如何避免异常

异常规范

C++98标准提出了异常规范,目的是为了让使用者知道函数可能会引发哪些异常。

void func1() throw(A, B,C);//表示该函数可能会抛出A、B、C类型的异常。
void func2() throw();//表示该函数不会抛出异常。
void func3();//该函数不符合C++98的异常规范。

C++11标准弃用了异常规范,使用新增的关键字noexcept指出函数不会引发异常。

void func4() noexcept;//该函数不会抛出异常。

在实际开发中,大部分程序员懒得在函数后面加noexcept,弃用异常已是共识,没必要多此一举。
关键字noexcept也可以用作运算符,判断表达试(操作数)是否可能引发异常;如果表达式可能引发异常,则返回false否则返回true。
在这里插入图片描述
对于下面的代码:

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
using namespace std;
int main() {//分配一大块内存double* ptr = nullptr;try {ptr = new double[100000000000];}catch (bad_alloc& e) {cout << "分配内存失败\n";}return 0;
}

我们使用这种也行:

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
using namespace std;
int main() {//分配一大块内存double* ptr = nullptr;ptr = new(std::nothrow) double[100000000000];if (ptr == nullptr)cout << "分配内存失败\n";//其他处理业务代码if (ptr != nullptr) delete[]ptr;return 0;
}

我们在实际开发中经常用这种,这种比较简单。

重点关注的异常

  1. std::bad_alloc
    如果内存不足,调用new会产生异常,导致程序中止;如果在new关键字后面加(std:nothrow)选项,则返回nullptr,不会产生异常。

  2. dynamic_cast
    dynamic_cast可以用于引用,但是,没有与空指针对应的引用值,如果转换请求不正确,会出现
    td::bad_cast异常。

  3. std:bad_typeid
    假设有表达式typeid(*ptr),当ptr是空指针时,如果ptr是多态的类型,将引发std:bad_typeid异常。

逻辑错误异常

程序的逻辑错误产生的异常std::logic_error,通过合理的编程可以避免。

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
using namespace std;
int main() {try {vector<int>vv = { 1,2,3 };//容器vv中只有三个元素vv.at(3) = 5;//将引发out_of_range异常}catch (out_of_range) {cout << "出现out_of_range异常\n";}return 0;
}
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
using namespace std;
int main() {//string str="123";//不会抛出异常//string str="";//将抛出Invalid_argument异常string str = "21212312312313123123123";//将抛出out_of_range异常try {int x = stoi(str);//将string字符串转化为整数cout << "x=" << x << endl;}catch (invalid_argument&) {cout << "出现invalid_argument异常\n";}catch (out_of_range&) {cout << "出现out_of_range异常\n";}return 0;
}

这个逻辑异常应该有程序员自己解决

C++断言

断言(assertion)是一种常用的编程手段,用于排除程序中不应该出现的逻辑错误。
使用断言需要包含头文件<cassert><assert.h>,头文件中提供了带参数的宏assert,用于程序
在运行时进行断言。

语法:assert(表达式);

断言就是判断(表达式)的值,如果为0(false),程序将调用abort()函数中止,如果为非0 (true),程序继续执行。
断言可以提高程序的可读性,帮助程序员定位违反了某些前提条件的错误。
例如:

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
#include<cassert>
using namespace std;
void copydata(void* ptr1, void* ptr2) {//把ptr2中的数据复制到ptr1中。assert(ptr1 && ptr2);//断言ptr1和ptr2都不会为空cout << "继续执行复制数据的代码....\n";}
int main() {int ii = 0, jj = 0;copydata(&ii, &jj);//把ptr2中的数据复制到ptr1中。return 0;
}

这个是正常的,就是把jj中的数据复制到ii中。
假如是这个代码:

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
#include<cassert>
using namespace std;
void copydata(void* ptr1, void* ptr2) {//把ptr2中的数据复制到ptr1中。assert(ptr1 && ptr2);//断言ptr1和ptr2都不会为空cout << "继续执行复制数据的代码....\n";}
int main() {int ii = 0, jj = 0;copydata(nullptr, &jj);//把ptr2中的数据复制到ptr1中。return 0;
}

在这里插入图片描述
注意:

  • 断言用于处理程序中不应该发生的错误,而非逻辑上可能会发生的错误。
  • 不要把需要执行的代码放到断言的表达式中。
  • 断言的代码一般放在函数/成员函数的第一行,表达式多为函数的形参,主要用于判断参数是否参数的合法性。

C++11 静态断言

assert宏是运行时断言,在程序运行的时候才能起作用。
C++11新增了静态断言static_assert,用于在编译时检查源代码。
使用静态断言不需要包含头文件。
语法: static_assert(常量表达式,提示信息);
用途: 在编译的时候,判断常量表达式的值,如果是0-false,那么编译失败,否则显示提示信息。
注意: static_assert的第一个参数是常量表达式。而assert 的表达式既可以是常量,也可以是变
量。

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>//ifstream 类需要包含的头文件
#include<string>
#include<cassert>
using namespace std;
void copydata(void* ptr1, void* ptr2) {//把ptr2中的数据复制到ptr1中。assert(ptr1 && ptr2);//断言ptr1和ptr2都不会为空cout << "继续执行复制数据的代码....\n";}
int main() {const int ii = 1, jj = 0;assert(ii);static_assert(ii, "ii的值不合法。");//copydata(nullptr, &jj);//把ptr2中的数据复制到ptr1中。return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/2152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Charles 工具如何做断点测试?

在测试工作过程中&#xff0c;我们经常会在程序的某一行或者某一环节设置断点&#xff0c;在程序请求的过程中&#xff0c;修改断点处的参数、请求或者响应&#xff0c;借此定位问题&#xff0c;这就是所谓的断点测试。这类断点测试主要用于接口测试。 断点测试可以通过查看接…

W801学习笔记十一:掌机进阶V3版本之硬件改造

经由前面的笔记&#xff0c;我们打造出了一款游戏掌机。 W801学习笔记十&#xff1a;HLK-W801制作学习机/NES游戏机(总结) 然而&#xff0c;考虑到后续的游戏开发&#xff0c;总是忧心容量不足。故而&#xff0c;在正式展开软件开发工作以前&#xff0c;最终进行一下升级改造…

maven多模块创建-安装配置

1、前提 许久没有写文章了&#xff0c;荒废了2年多的时间&#xff0c;在整理的时候&#xff0c;发现Maven还差一篇安装配置的文章&#xff0c;现在开始提笔完善它&#xff0c;参考&#xff1a;https://blog.csdn.net/m0_72803119/article/details/134634164。 —写于2024年4月…

LeetCode - 11.盛最多水的容器

一. 题目链接 LeetCode - 11.盛最多水的容器 二. 思路解释 利用双指针的思想&#xff0c;定义一个left和reght&#xff0c;left指向首部&#xff0c;right指向尾部&#xff0c;计算当前两个指针所对应的高度构成容器的体积。根据当前双指针所指的高度的大小&#xff0c;然后让…

linux服务器和RAID磁盘阵列

1、服务器 &#xff08;1&#xff09;服务器分类 机架式居多 塔式 刀片式 机柜式 机架式 机架式服务器是一种服务器的机箱形式&#xff0c;它被设计为在服务器机架或机柜中安装。机架式服务器通常具有标准的19英寸宽度&#xff0c;并且可以根据服务器的高度进行划分&#xff0…

富唯智能:打造未来机器人教育新标杆

随着科技的飞速发展&#xff0c;机器人教育正逐渐成为培养未来人才的重要领域。富唯智能&#xff0c;作为业内领先的机器人技术提供商&#xff0c;近日推出了一款全新的机器人教育实践平台系统&#xff0c;旨在为学生提供更加丰富、更具挑战性的学习体验。 该平台系统以AUBO-i5…

电力监控系统是什么,有哪些功能

电力监控系统是什么,有哪些功能 电力是国家重要的基础设施&#xff0c;电力监控系统用于监视和控制电力生产和供应过程&#xff0c;是电力安全稳定运行的支撑系统。 什么是电力监控系统&#xff1f; 电力监控系统是指用于监视和控制电力生产及供应过程的、基于计算机及网…

上网行为管理软件有哪些?三款常用上网行为管理软件评测

互联网的普及&#xff0c;企业和个人对于网络安全和信息保护的需求越来越高。为了确保网络环境的安全和稳定&#xff0c;上网行为管理软件应运而生。本文将对三款常用的上网行为管理软件进行评测&#xff0c;分别是域智盾、Splunk Enterprise Security和安企神。 1、域智盾 域…

Linux查看僵尸进程

1、查看系统是否有僵尸进程 使用Top命令查找&#xff0c;当zombie前的数量不为0时&#xff0c;即系统内存在相应数量的僵尸进程。 2、定位僵尸进程 使用命令ps -A -ostat,ppid,pid,cmd |grep -e ‘^[Zz]’定位僵尸进程以及该僵尸进程的父进程。 3、杀死僵尸进程 使用Kill -…

二叉树中的最长交错路径

题目链接 二叉树中的最长交错路径 题目描述 注意点 每个节点的值在 [1, 100] 之间 解答思路 深度优先遍历整棵树&#xff0c;遍历的同时需要将到达根节点是向左交叉还是向右交叉以及路径长度传递到子树。当根节点是向左交叉遍历而来&#xff0c;子树想和根节点组成路径就只…

<计算机网络自顶向下> 面向连接的传输:TCP

目录 TCP: 概述 TCP报文段结构 TCP往返延时&#xff08;RTT&#xff09;和超时 可靠数据传输 快速重传 流量控制 连接管理 TCP: 概述 点对点 一个发送方&#xff0c;一个接收方可靠的、按顺序的字节流 不出错&#xff0c;不重复&#xff0c;不丢失&#xff0c;不失序没有报…

面试算法准备:动态规划

这里写自定义目录标题 1 理论2 例题2.1 斐波那契数列&#xff08;什么是重叠子问题&#xff09;2.1.1 带备忘录的递归解法 2.2 零钱兑换&#xff08;讲解最优子结构&#xff09;2.3 最长递增子序列&#xff08;讲解如何求解状态转移方程&#xff09;2.4 俄罗斯套娃信封问题&…

3月养颜抗氧化市场发展趋势洞察:抗糖亮肤功能性产品成为行业大势

随着我国人口老龄化程度的加深和人们对健康和美丽的追求日益增强&#xff0c;具备养颜抗氧化、抗衰老功能的产品逐渐成为市场热门&#xff0c;备受人们关注。 根据鲸参谋数据显示&#xff0c;今年3月份&#xff0c;在线上电商平台&#xff08;京东天猫淘宝&#xff09;养颜抗氧…

[Windows] Bypass分流抢票 v1.16.25 五一黄金周自动抢票软件(2024.02.08更新)

五一黄金周要来了&#xff0c;火车票难买到&#xff0c;即便官网候选订票也要看运气&#xff0c;推荐使用这个靠谱的自动抢票软件&#xff0c; 该工具是目前市面上最好用口碑最好的电脑抢票软件&#xff0c;从13年到现在&#xff0c;作者依旧在更新&#xff0c;可以自动识别123…

什么是最优物理隔离文件导出导入解决方案,来看看吧

企业进行物理隔离的主要原因是为了提高安全性&#xff0c;减少安全风险。物理隔离通常指的是将网络或系统中的关键部分与外界断开直接连接&#xff0c;以增强安全性。在企业环境中&#xff0c;这通常意味着将内部网络&#xff08;内网&#xff09;与外部网络&#xff08;如互联…

关于MCU核心板的一些常见问题

BGA植球与焊接&#xff08;多涂焊油&#xff09;&#xff1a; 【BGA芯片是真麻烦&#xff0c;主要是植锡珠太麻烦了&#xff0c;拆一次就得重新植】https://www.bilibili.com/video/BV1vW4y1w7oNvd_source3cc3c07b09206097d0d8b0aefdf07958 / NC电容一般有两种含义&#xff1…

控制台居然可以这么玩?五分钟带你上手ANSI指令,实现一个log工具包

目录 前言 基础知识 进阶实践 ANSI参数 ANSI类 JSLog类 工具的使用说明 配置相关 全局配置项 默认配置 基本用法 打印字符 添加全局配置项 清空所有样式及操作行为 校验传入的参数是否正确 样式控制 Node环境 浏览器中 光标控制指令 光标位置偏移 滚动条控…

消费增值:革新你的消费体验,让每一分钱都更有价值

亲爱的顾客们&#xff0c;你们好&#xff01;今天&#xff0c;我想为大家介绍一种革新性的消费模式——消费增值&#xff0c;它赋予每一次购物以额外的价值&#xff0c;让消费过程变得更加丰富多彩。 过去&#xff0c;我们的消费观念往往是“一手交钱&#xff0c;一手交货”&am…

LCD彩屏显示方案选型攻略:从接口到GUI开发工具的全面评估

在现代人类社会&#xff0c;彩色显示技术是科技王国里最为绚丽夺目的技术奇葩&#xff0c;LCD彩屏通过显示实时信息并提供交互式的体验&#xff0c;将信息时代打扮得多姿多彩。无论是智能家电还是医疗健康设备领域&#xff0c;精美直观的LCD彩屏显示&#xff0c;往往能够为用户…

【Linux学习】初始冯诺漫体系结构

文章目录 认识冯诺依曼系统 认识冯诺依曼系统 什么是冯诺依曼体系结构&#xff1f; 冯诺依曼体系结构是一种将程序指令和数据以二进制形式存放在主存储器中&#xff0c;由中央处理器统一控制和执行的计算机系统结构。冯诺依曼体系结构实现了程序的可编程性和硬件与软件的分离&…