C++11异常的使用方法和优缺点介绍

这篇具有很好参考价值的文章主要介绍了C++11异常的使用方法和优缺点介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

异常

C98的错误处理机制:1、终止程序,如assert,缺陷:程序直接退出。如发生内存错误,除0错误时就会终止程序;2、返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误。

在实际使用中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。

C++11引入了异常概念。

概念

异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。

关键字throw、catch、try

throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。throw后要跟的是一个对象

catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常,可以有多个catch进行捕获。没有发生异常就会直接跳过catch最后要有个catch(...)。【像是switch case语句里面的default】

try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。

如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。

格式

try
{
 // 保护的标识代码
}
catch( ExceptionName e1 )
{
 // catch 块
}
catch( ExceptionName e2 )
{
 // catch 块
}
catch(...)
{
 //实际中我们最后都要加一个catch(...)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
}

捕获到什么就抛出什么

try{}
catch(...)
{
	throw;
}

异常的使用

异常的抛出和捕获的匹配原则

要注意!!类型匹配:throw的对象类型和catch接收的对象类型要一致!就近原则:抛出的异常由1个离得最近的catch处理!第一个:抛出多个异常也只会抛出第1个异常!

  1. 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码,同一个try-catch语句里,多个catch不可以接收同一个对象类型
  2. 若抛出的异常没有被catch,进程直接终止;
  3. 被选中的catch处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个,即一次抛出多个异常也只有1个catch来处理
  4. 捕获的是对象的拷贝,出了catch就销毁!抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁;(这里的处理类似于函数的传值返回)
  5. catch(...)可以捕获任意类型的异常,但是我们不知道异常错误是什么;
  6. 实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象,使用基类捕获,这个在实际中非常实用,后续详细讲解。

在函数调用链中异常栈展开匹配原则

首先检查throw本身是否在try块内部,在的话就查找匹配的catch语句->如果有匹配的则调到catch的地方进行处理;没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch;如果到达main函数的栈,依旧没有匹配的,则终止程序。

上述这个沿着调用链查找匹配的catch子句的过程称为栈展开。所以实际中我们最后都要加一个catch(...)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止,找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。

异常引发的安全问题

  1. 构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化;
  2. 析构函数主要完成资源的清理,最好不要在析构函数内抛出异常,否则可能导致资源泄漏(内存泄漏、句柄未关闭等);
  3. C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,在lock和unlock之间抛出了异常导致死锁,C++经常使用RAII来解决以上问题,关于RAII在智能指针再讲解。

异常的重新抛出

有可能单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。也可以利用重新抛出来解决异常引发的安全问题。

C98异常规范

异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些,C++函数后面加关键字throw(something)限制,是对这个函数的异常安全性作出限制。(注:c++11使用noexcept)

  1. 可以在函数的后面接throw(类型),列出这个函数可能抛掷的所有异常类型。

    void fun() throw(exceptionType) 表示fun只能抛出exceptionType类型的异常;

    void fun() throw(A,B,C,D);表示这个函数会抛出A/B/C/D中的某种类型的异常

  2. 函数的后面接throw(),表示函数不抛异常。

    void fun() throw() 表示fun不允许抛出任何异常。

  3. 若无异常接口声明,则此函数可以抛掷任何类型的异常。

    void fun() throw(...) 表示fun可以抛出任何形式的异常。

C11–noexcept关键字

用noexcept修饰的函数不会抛出异常,在c++11中,如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()来终止程序的运行,这比基于异常机制的throw()在效率上会高出一些。使用noexcept可有效阻止异常的传播与扩散。

STL的异常体系

  1. std::exception 该异常是所有标准 C++ 异常的父类。
  2. std::bad_alloc 该异常可以通过 new 抛出。内存申请失败就会抛异常。void* operator new (std::size_t size) throw (std::bad_alloc);
  3. std::bad_cast 该异常可以通过 dynamic_cast 抛出。
  4. std::bad_exception 这在处理 C++ 程序中无法预期的异常时非常有用。
  5. std::bad_typeid 该异常可以通过 typeid 抛出。
  6. std::logic_error 理论上可以通过读取代码来检测到的异常。
  7. std::domain_error 当使用了一个无效的数学域时,会抛出该异常。
  8. std::invalid_argument 当使用了无效的参数时,会抛出该异常。
  9. std::length_error 当创建了太长的 std::string 时,会抛出该异常。
  10. std::out_of_range 该异常可以通过方法抛出,例如 std::vector 的at访问超出有效数据范围和 std::bitset<>::operatoroperator[]使用assert。
  11. std::runtime_error 理论上不可以通过读取代码来检测到的异常。
  12. std::overflow_error 当发生数学上溢时,会抛出该异常。
  13. std::range_error 当尝试存储超出范围的值时,会抛出该异常。
  14. std::underflow_error 当发生数学下溢时,会抛出该异常。

通过继承和重载 exception 类来定义新的异常,what() 是异常类提供的一个公共方法,它已被所有子异常类重载。这将返回异常产生的原因。

异常的优缺点

优点:相比错误码的方式可以清晰准确的展示出错误的各种信息,甚至可以包含堆栈调用的信息,这样可以帮助更好的定位程序的bug;boost、gtest、gmock等等常用的第三方库都在使用异常;异常适用于如错误码若调用层数太深就比较麻烦,assert只在debug模式下有效的其他报错有缺陷的情况。

缺点:异常会导致程序的执行流乱跳,非常混乱;容易导致内存泄漏、死锁等异常安全问题,要使用RAII来处理资源的管理问题;文章来源地址https://www.toymoban.com/news/detail-405516.html

到了这里,关于C++11异常的使用方法和优缺点介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • singularity 运行方式汇总,运行方式的优缺点,及其调用方法

    1. Shell 模式 调用方法 : singularity shell [options] container_path 优点 : 提供了一个交互式的环境,用户可以在容器内探索和运行命令,非常适合开发和测试。 不需要预先定义要运行的命令或脚本,增加了灵活性。 缺点 : 交互式使用可能不适合自动化脚本或批处理作业。 在容器内手

    2024年02月22日
    浏览(27)
  • 【设计模式】工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    【设计模式】工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )_工厂方法模式的优缺点_韩曙亮的博客-CSDN博客

    2024年02月16日
    浏览(30)
  • C#实例方法和静态方法有区别吗?各自的优缺点有哪些?

      实例方法和静态方法之间有几个关键的区别: 关联对象:  实例方法是与对象实例相关联的,必须通过实例来调用。 this :  实例方法中可以使用  this  引用当前实例。 访问实例成员:  实例方法可以直接访问和修改实例的字段、属性和其他成员。 生命周期

    2024年01月18日
    浏览(38)
  • FPGA图像处理的一些方法、原理和算法优缺点介绍

    目录 一、FPGA图像处理的基本原理 二、FPGA图像处理的方法 1. 图像滤波 2. 边缘检测 3. 图像分割 4. 图像增强 5. 图像目标提取算法 6. 注意事项 三、FPGA图像处理的应用 1. 医学影像 2. 工业检测 3. 安防监控 四、总结 注意:后续技术分享,第一时间更新,以及更多更及时的技术资

    2024年02月15日
    浏览(33)
  • MySQL~索引的优缺点是什么?有哪些优化索引的方法?

    优点:提高查询记录的速度。 缺点: 需要占用空间,索引是一种用空间换时间的做法 创建索引和维护索引都需要消耗时间,会降低表的增删查改效率,因为每次进行增删查改,都需要对索引进行维护,需要消耗时间 经常作为查询条件的字段 ,如果需要同时查找多个字段,

    2024年02月16日
    浏览(35)
  • js常用判断数据类型方法以及优缺点 以及 instanceof 原理实现

    使用typeof操作符可以 判断一个值的数据类型 。它返回一个表示数据类型的字符串。 优点:typeof 操作符是一种简单、快速的方式来 判断基本数据类型 。它返回的结果是一个字符串,可以直接用于条件判断。 缺点: 对于引用类型(除了函数)的判断结果都是\\\'object\\\' ,无法细

    2024年02月12日
    浏览(31)
  • 浅谈 iframe的优缺点以及使用场景

    提示:以下是本篇文章正文内容 iframe 是嵌入式框架,是 HTML框架 ,还是一个 内联元素 ,iframe元素会创建包含另一个文档的内联框架(行内框架),说白了就是,iframe用来在页面嵌入其他的页面。 通常我们使用iframe直接在页面嵌套iframe标签指定src就可以了。 iframe能够把嵌入

    2024年02月05日
    浏览(38)
  • 浅析switch和if(开发中这两者的优缺点;分析出优缺点在使用就能更确定自己需要使用哪个函数了)

    分析: switch是在编译阶段将子函数的地址和判断条件绑定了,只要直接将a的直接映射到子函数地址去执行就可以了, if处理起来首先要把a的值放到CPU的寄存器中,然后要把比较的值放到CPU的另一个寄存器中,然后做减法,然后根据计算结果跳转到子函数去执行,这样一来就

    2024年02月09日
    浏览(41)
  • MySQL、Redis 和 Zookeeper 实现分布式锁方法及优缺点

    MySQL、Redis 和 Zookeeper 都可以用来实现分布式锁,每种技术都有其特定的实现方法以及各自的优缺点。 MySQL 分布式锁 实现方法 在 MySQL 中实现分布式锁通常涉及到使用数据库表。可以创建一个专用的锁表,并利用行的唯一性(例如利用唯一索引)来实现锁机制。 使用基于事务

    2024年04月11日
    浏览(31)
  • Edge浏览器的使用体验及优缺点

    🔍【浏览器必备】你们用哪个浏览器呀?相信大家都有各自喜欢的浏览器吧。今天小编要给大家介绍一款浏览器,它就是——Microsoft Edge! 🌟【品牌介绍】Microsoft Edge是由微软公司推出的全新浏览器,它是Windows 10的默认浏览器,也可以在其他操作系统上使用,如MacOS和Andro

    2024年02月08日
    浏览(95)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包