跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 异常规范
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:C++异常规范}} '''C++异常规范'''(Exception Specifications)是C++中用于声明函数可能抛出的异常类型的机制。它允许程序员显式指定函数可能抛出的异常类型,从而提供更好的代码可读性和安全性。然而,随着C++标准的演进(特别是C++11之后),异常规范的用法发生了重大变化,本文将从基础到高级全面讲解这一特性。 == 概述 == C++异常规范分为两种形式: 1. '''动态异常规范'''(C++98引入,C++17移除):使用<code>throw(type1, type2)</code>语法 2. '''noexcept规范'''(C++11引入):使用<code>noexcept</code>或<code>noexcept(expr)</code>语法 异常规范的主要目的是: * 作为函数接口的文档 * 允许编译器进行优化 * 在违反规范时调用<code>std::unexpected()</code>(动态异常规范) == 动态异常规范(已废弃) == === 基本语法 === <pre> 返回类型 函数名(参数列表) throw(异常类型列表); </pre> 示例: <syntaxhighlight lang="cpp"> #include <stdexcept> void foo(int x) throw(std::runtime_error, std::logic_error) { if (x < 0) { throw std::runtime_error("Negative value"); } if (x > 100) { throw std::logic_error("Value too large"); } // 抛出未列出的异常将导致std::unexpected()被调用 } </syntaxhighlight> === 特殊形式 === * <code>throw()</code>:表示不抛出任何异常(C++11后可用<code>noexcept</code>替代) * 无异常规范:可以抛出任何异常 === 为什么被废弃 === 动态异常规范在实践中存在以下问题: 1. 运行时检查而非编译时检查 2. 性能开销 3. 难以维护(函数签名变更需同步更新异常规范) 4. 与模板结合使用困难 == noexcept规范(现代替代方案) == C++11引入的<code>noexcept</code>规范更简单高效,成为推荐做法。 === 基本语法 === <syntaxhighlight lang="cpp"> void func1() noexcept; // 绝不抛出异常 void func2() noexcept(true); // 同noexcept void func3() noexcept(false); // 可能抛出异常 </syntaxhighlight> === noexcept运算符 === <code>noexcept(expr)</code>可在编译期检查表达式是否可能抛出异常: <syntaxhighlight lang="cpp"> template <typename T> void swap(T& a, T& b) noexcept(noexcept(T(std::move(a))) && noexcept(a.operator=(std::move(b)))) { // 实现... } </syntaxhighlight> === 实际应用示例 === 移动构造函数通常应标记为<code>noexcept</code>: <syntaxhighlight lang="cpp"> class Resource { int* data; public: Resource(Resource&& other) noexcept : data(other.data) { other.data = nullptr; } // ... 其他成员函数 }; </syntaxhighlight> == 异常规范的影响 == === 对代码生成的影响 === 编译器可能基于<code>noexcept</code>进行优化: * <code>noexcept</code>函数不需要生成栈展开代码 * STL容器对<code>noexcept</code>移动操作有特殊处理 === 标准库使用 === 标准算法通常要求可调用对象为<code>noexcept</code>: <syntaxhighlight lang="cpp"> std::vector<MyType> v; // 如果MyType的移动构造函数是noexcept,vector.resize可能使用移动而非复制 v.resize(100); </syntaxhighlight> == 最佳实践 == 1. 优先使用<code>noexcept</code>而非动态异常规范 2. 移动操作、析构函数、交换操作应尽量标记为<code>noexcept</code> 3. 不应对可能失败的函数(如内存分配)使用<code>noexcept</code> 4. 在接口设计中明确异常保证级别: * 无异常(noexcept) * 基本异常安全(操作失败时对象状态有效) * 强异常安全(操作失败时状态不变) * 无异常安全(可能泄漏资源) == 示例:异常安全类设计 == <syntaxhighlight lang="cpp"> class DatabaseConnection { ConnectionHandle handle; public: DatabaseConnection() noexcept : handle(nullptr) {} void connect(const std::string& url) { ConnectionHandle new_handle = open_connection(url); // 可能抛出 handle = new_handle; // 仅当成功时修改状态(强异常安全) } ~DatabaseConnection() noexcept { if (handle) close_connection(handle); } DatabaseConnection(DatabaseConnection&& other) noexcept : handle(other.handle) { other.handle = nullptr; } DatabaseConnection& operator=(DatabaseConnection&& other) noexcept { std::swap(handle, other.handle); return *this; } // 禁用复制 DatabaseConnection(const DatabaseConnection&) = delete; DatabaseConnection& operator=(const DatabaseConnection&) = delete; }; </syntaxhighlight> == 历史演变 == <mermaid> timeline title C++异常规范演变 section C++98 动态异常规范 : throw(type1, type2) 空规范 : throw() section C++11 noexcept 引入 : 替代throw() 条件noexcept : noexcept(expr) 弃用动态规范 section C++17 移除动态异常规范 保留throw()作为noexcept别名 section C++20 noexcept 成为类型系统的一部分 </mermaid> == 数学表示 == 异常规范可以形式化表示为函数签名的一部分: <math> F \colon \text{Parameters} \rightarrow \text{ReturnType} \quad \text{with} \quad \text{ExceptionSpec} </math> 其中ExceptionSpec可以是: * <math>\emptyset</math>(无异常保证) * <math>\{\text{type}_1, \text{type}_2, ...\}</math>(动态规范) * <math>\text{noexcept}</math>(无异常) == 总结 == * 现代C++应使用<code>noexcept</code>而非动态异常规范 * 异常规范影响代码优化和接口设计 * 合理使用异常规范可以提高代码可靠性和性能 * 析构函数默认应标记为<code>noexcept</code> * 移动操作通常应标记为<code>noexcept</code>以获得最佳性能 {{C++异常处理导航}} [[Category:编程语言]] [[Category:C++]] [[Category:C++ 异常处理]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
模板:C++异常处理导航
(
编辑
)