异常安全:指当异常发生时,既不会发生资源泄漏,系统也不会处于一个不一致的状态
异常的问题
异常违反了”你不用就不需要付出代价”的C++原则。只要开启了异常,即使不使用异常你编译出的二进制代码通常也会膨胀
目前主流的异常实现中,都倾向于牺牲可执行文件大小、提供主流程的性能。
异常比较隐蔽,不容易看出来哪些地方会发生异常和发生什么异常
和Java 不同,C++里不会对异常规约进行编译时的检查。从C++17开始,C++甚至完全禁止了以往的动态异常规约,你不再能在函数声明里写你可能抛出某某异常。你唯一能声明的,就是某函数不会抛出异常–noexcept、noexcept(true) 或 throw()。这也是C++的运行时唯一会检查的东西。如果一个函数声明了不会抛出异常、结果却抛出了异常,C++运行时会调用 std::terminate 来终止应用程序
不使用异常是有理由的。特别是在泛型编程的代码中,几乎不可能预知会发生些什么异常。个人建议
- 写异常安全的代码,尤其在模板里。可能的话,提供强异常安全保证,在任何第三方代码发生异常的情况下,不改变对象的内容,也不产生任何资源泄漏
- 如果你的代码可能抛出异常的话,在文档里明确声明可能发生的异常类型和发生条件。确保使用你的代码的人,能在不检查你的实现的情况,了解需要准备哪些异常
- 对于肯定不会抛出异常的代码,将其标为 noexcept。注意类的特殊成员(构造函数、析构函数、赋值函数)会自动成为 noecxept,如果他们调用的代码都是 noexcept 的话。所以,像 swap 这样的成员函数应该尽可能标为 noexcept。