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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

macbook内存怎么清理?2024年有哪些好用的软件

当你的MacBook运行缓慢时&#xff0c;这很可能是因为内存&#xff08;RAM&#xff09;满了。内存是计算机的临时存储区&#xff0c;用于存放当前正在使用的程序和数据。当内存满时&#xff0c;MacBook就会使用硬盘作为临时内存&#xff0c;这大大降低了运行速度。那么&#xff…

Hadoop3:HDFS、YARN、MapReduce三部分的架构概述及三者间关系(Hadoop入门必须记住的内容)

一、HDFS架构概述 Hadoop Distributed File System&#xff0c;简称HDFS&#xff0c;是一个分布式文件系统。 1&#xff09;NameNode(nn)&#xff1a;存储文件的元数据&#xff0c;如文件名&#xff0c;文件目录结构&#xff0c;文件属性&#xff08;生成时间、副本数、文件…

基于Tensorflow完成mnist数据集的数字手写体识别

基于Tensorflow完成mnist数据集的数字手写体识别 关于知识背景CNNFCNN 关于数据集新的改变 关于知识背景 CNN 卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;是一种具有局部连接、权值共享等特点的深层前馈神经网络&#xff08;Feed…

【CAD打开提示未处理异常C0000027(c0000027h)的两种解决方法。】

cad打开提示错误c0000027h的第一种解决方法 去掉区域里的beta语言勾选。 https://autodesk8.com/cad/86.html 如果第一种方法没解决&#xff0c;尝试第二种方法大概率能解决 点击autoremove的扩展功能&#xff0c;输入c0000027点击搜索&#xff0c;然后双击出现的这个按钮既可…

【AI开发:音频】一、GPT-SoVITS整合工具包的部署问题解决(GPU版)

前言 目前GPT-SoVITS的合成效果比较不错&#xff0c;相比较其他厂商的产品要规整的多。众多厂家中也是国内使用最多的一款了&#xff0c;并且这个整合包里携带了&#xff0c;除背景音、切割、训练、微调、合成、低成本合成等一些列完整的工具&#xff0c;也可以作为API进行使用…

近年数一,数二难度如何,听说24是像张宇那样的题?

直接上分数&#xff01; “估分一百零几&#xff0c;平时李林130-140&#xff0c;张八110-125的样子&#xff0c;超越做的分数也是100出头。” 24学长说&#xff1a; “远离李林张八&#xff01;张四没做不评价。” “李林张八暑假前做完当作打基础即可。超越才是真题难度”…

利用regress绘制拟合图,利用Slope的趋势分析(5)

code如下&#xff1a; % SCD,积雪日数 % SCS,积雪初日 % SCM,积雪终日% SCS SCD SCM clc; clear; % 读取 Excel 表 excel_file E:\work\2024年\April20\积雪作图\tif文件\excel表\SCS.xlsx; % Excel 文件路径 data readtable(excel_file);datavalue data{:,2:end}; year (…

【工具-pip】

工具-pip ■ pip-工具■ pip-安装■ pip-卸载■ pip-帮助■ pip- 批量安装库■ 批量卸载库■ 提高pip下载速度 ■ pip-工具 pip 是 Python 标准库中的一个包&#xff0c;这个包是用来管理 Python 第三方库。 通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、…

【分治算法】Hanoi塔问题Python实现

文章目录 [toc]问题描述Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python基础 学习指南&#xff1a;Python学习指南 问题描述 设 a a a、 b b b、 c c c是三个塔座&#xff0c;开始时&#xff0c;在塔座 a a a上有一叠共 n n n个圆盘&#xff0c;这些圆盘…

设备运行远程监控系统

在信息化、智能化的浪潮下&#xff0c;设备运行远程监控系统已经成为企业提升运营效率、降低运营成本、保障生产安全的重要工具。HiWoo Cloud作为设备运行远程监控系统&#xff0c;以其卓越的性能和稳定的运行&#xff0c;赢得了众多企业的青睐。 一、设备运行远程监控系统的概…

动手学大模型应用开发--Chapter 03搭建并使用向量数据库

文章目录 前言一、学习目标二、学习知识点概要2.1 什么是词向量2.2 词向量的意义2.3 文本转为词向量的方法 三、总结四、引申阅读 前言 本学习笔记为datawhale动手学大模型应用开发的第三章&#xff0c;学习链接为&#xff1a; https://datawhalechina.github.io/llm-universe…

ARTS Week 24

Algorithm 本周的算法题为 21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; img 输入&#xff1a;list1 [1,2,4], list2 [1,3,4]输出&#xff1a;[1,1,2,3,4,4] 实现代码如下&…

Web3钱包开发获取测试币-Polygon Mumbai(一)

Web3钱包开发获取测试币-Polygon Mumbai(一) 由于主网区块链上的智能合约需要真正的代币&#xff0c;而部署和使用需要花费真金白银&#xff0c;因此测试网络为 Web3 开发人员提供了一个测试环境&#xff0c;用于部署和测试他们的智能合约&#xff0c;以识别和修复在将智能合约…

海康Visionmaster-常见问题排查方法-安装阶段

VM软加密安装失败&#xff0c;报错&#xff1a;软件未激活&#xff0c;是否进行授权激活&#xff1b; 解决方法&#xff1a;如确认已完成授权&#xff0c;此时打上试用用补丁即可。补充VM400试用版本正确安装顺序如下&#xff1a; 安装顺序&#xff1a; ①安装基础安装包&…

计算机网络3——数据链路层5高速以太网

文章目录 一、100BASE-T 以太网二、吉比特以太网三、10吉比特以太网(10GbE)和更快的以太网四、使用以太网进行宽带接入 随着电子技术的发展&#xff0c;以太网的速率也不断提升。从传统的10Mbits以太网一直发展到现在常用的速率为1Gbits的吉比特以太网&#xff0c;甚至更快的以…

项目管理中,项目团队如何高效的协作与沟通?

目 录 一、项目团队高效的协作与沟通&#xff0c;可以通过以下几个方面来实现&#xff1a; 二、如何在项目团队中明确和共享愿景以提高协作效率&#xff1f; 三、有效的沟通策略在项目管理中的应用案例有哪些&#xff1f; 四、建立哪些具体的沟通机制可以提升团队协作效率…

网络安全与密码学--AES加密

分组加密之AES加密算法 AES算法的诞生 python实现AES加密 AES加密详细流程 AES解密过程 AES的应用 1997年 NIST征集AES&#xff08;Advanced Encryption Standard&#xff09;2000年选中 https://www.nist.gov/ https://csrc.nist.gov/projects/block-cipher-techniques A…

基于vue+node+mysql的视频校对系统

一、登录注册&#xff1a;包括登录&#xff0c;注册&#xff0c;忘记密码&#xff0c;验证码等常用点。 二、用户管理&#xff1a;包括用户的增删改查 三、权限管理&#xff08;请增加这个权限&#xff1a;任务分配——只有管理者才能发布和删除任务&#xff1b;管理员设置。 四…

ESLlint重大更新后,使用旧版ESLint搭配Prettier的配置方式

概要 就在前几天&#xff0c;ESLint迎来了一次重大更新&#xff0c;9.0.0版本&#xff0c;根据官方文档介绍&#xff0c;使用新版的先决条件是Node.js版本必须是18.18.0、20.9.0&#xff0c;或者是>21.1.0的版本&#xff0c;新版ESLint将不再直接支持以下旧版配置(非扁平化…

阿斯达年代记怎么下载 阿斯达年代记三强争霸下载教程

阿斯达年代记怎么下载 阿斯达年代记三强争霸下载教程 阿斯达年代记是一款三国争霸类型的游戏&#xff0c;在游戏中大家可以体验到三权争霸的刺激场景&#xff0c;在战场中大家不仅可以体验到体验到文化交织还可以感受到战场的残酷&#xff0c;本期小编将会给大家带来阿斯达年代…