c++如何捕获标准异常与自定义异常_c++ try-catch块与noexcept使用【教程】


标准异常可用 catch (const std::exception&) 捕获,自定义异常须继承 std::exception(如 std::runtime_error)并按具体到宽泛顺序捕获,否则会跳过或崩溃。

标准异常能用 catch (const std::exception& e) 捕获,但自定义异常必须显式声明类型;noexcept 不是“不抛异常”的保证,而是编译期契约——违反它会直接调用 std::terminate

如何正确捕获标准异常和自定义异常

标准异常(如 std::runtime_errorstd::out_of_range)都继承自 std::exception,所以用基类引用捕获是安全的。但自定义异常若没继承 std::exception,就不能被 catch (const std::exception&) 捕获,会跳过并终止程序。

常见错误现象:自定义类 MyError 直接 throw MyError{},却只写 catch (const std::exception&),结果崩溃。

  • 自定义异常应显式继承 std::exception 或其派生类(推荐 std::runtime_error
  • 捕获顺序必须从具体到宽泛:先 catch (const MyError&),再 catch (const std::exception&),否则后者会吞掉前者
  • 不要用 catch (...) 代替具体捕获——它无法获取异常信息,且掩盖类型意图
class MyError : public std::runtime_error {
public:
    MyError(const std::string& msg) : std::runtime_error("MyError: " + msg) {}
};

// 正确捕获顺序
try {
    throw MyError{"failed"};
} catch (const MyError& e) {
    std::cout << "Custom: " << e.what() << "\n";
} catch (const std::exception& e) {
    std::cout << "Std: " << e.what() << "\n";
}

noexcept 的真实作用与误用场景

noexcept 是函数声明的一部分,告诉编译器“这个函数承诺不抛出任何异常”。它不是运行时检查,也不影响函数体内部能否 throw;一旦违反,程序立即调用 std::terminate,没有栈展开,无法 catch

典型误用:给可能调用 newstd::string 构造的函数加 noexcept,而没考虑内存分配失败(std::bad_alloc)。

  • noexcept 函数内仍可 throw,但会导致未定义行为(实际就是终止)
  • 移动构造/移动赋值函数加 noexcept 是关键——容器(如 std::vector)在扩容时依赖它决定是否用移动而非拷贝
  • noexcept(true)noexcept(false) 显式标注更清晰;省略时默认为 noexcept(false)
struct Widget {
    std::string data;
    
    // ✅ 移动构造加 noexcept,让 vector::reserve 能安全移动
    Widget(Widget&& other) noexcept : data(std::move(other.data)) {}
    
    // ❌ 若这里抛异常(比如 data 移动时分配失败),程序直接 terminate
    Widget(int x) noexcept { 
        if (x < 0) throw std::invalid_argument("x must be >= 0"); // 违反 noexcept!
    }
};

try-catch 块中容易忽略的资源管理问题

catch 块里手动 delete 或关闭文件,极易遗漏或重复释放。C++ 异常安全的核心不是靠 catch 补救,而是靠 RAII。

常见错误现象:在 trynew int[100],然后在 catchdelete[] p —— 如果 catch 里又抛异常,内存就泄漏了。

  • 永远优先用智能指针(std::unique_ptr)、容器(std::vector)、RAII 封装类(如 std::fstream)管理资源
  • catch 块只做错误分类、日志、转换或恢复决策,不负责资源清理
  • 需要“无论是否异常都执行”的逻辑,用 lambda + std::shared_ptr 自定义删除器,或 C++20 的 std::scope_exit(需自行实现兼容版)

最常被绕开的点:noexcept 的契约性比看起来更硬,它不接受 runtime 权衡;而自定义异常的类型安全性,完全取决于你是否真的让它继承 std::exception——光名字像没用。


# ai  # c++  # String  # 封装  # try  # throw  # catch  # const  # int  # Lambda  # 指针  # 继承  # fstream  #   # delete  # 自定义  # 跳过  # 也不  # 就不能  # 你是否  # 让它  # 而非  # 它会  # 它不  # 只做 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  Win11怎么恢复旧版开始菜单_通过软件还原Win10风格菜单【详解】  phpstudy本地环境mysql忘记密码_重置mysqlroot密码操作流程【解答】  Win11如何设置系统声音_Win11系统声音调整教程【攻略】  Win11开机Logo怎么换_Win11自定义启动画面工具【高级】  Win11怎么退出微软账户_切换Win11为本地账户登录方法【详解】  Win11如何设置自动关机 Win11定时关机命令使用教程【技巧】  Windows10系统怎么查看显卡驱动_Win10设备管理器驱动更新  windows如何修改文件默认打开方式_windows设置程序关联教程  MAC怎么使用表情符号面板_MAC Emoji快捷键调用与符号查找【方法】  mac怎么打开终端_MAC终端Terminal使用入门与常用命令【教程】  Win11怎么关闭自动维护 Win11禁用系统自动维护功能【优化】  Win11如何设置电源计划_Win11电源计划优化教程【攻略】  为什么Go需要go mod文件_Go go mod文件作用说明  Python异步网络编程_aiohttp说明【指导】  php下载安装后memory_limit怎么设置_内存限制调整【技巧】  MAC如何隐藏文件夹及文件_MAC终端命令隐藏与第三方工具加密【教程】  Win11怎么更改系统语言_Win11中文语言包下载与安装【指南】  Windows电脑如何截屏?(四种快捷方法)  如何在Golang中实现邮件发送功能_Golang SMTP发送与错误处理示例  Win11 C盘满了怎么清理 Win11磁盘清理和存储感知使用教程【新手必看】  如何使用Golang安装依赖库_管理模块和第三方包  c++ atoi和atof函数用法_c++字符数组转数字  如何使用Golang实现多重错误处理_Golangerror组合与判断方法  如何使用Golang理解结构体指针方法接收者_Golang修改字段实践  php转exe用什么工具打包快_高效打包软件推荐【汇总】  c++怎么使用std::filesystem遍历文件夹_c++ 递归查找文件与权限修改【技巧】  Win11怎么开启窗口对齐助手_Windows11系统多任务处理设置  如何在 Go 中调用动态链接库(.so)中的函数  Win11怎么设置声音输出设备_Windows11音量合成器单独调节应用  Win10电脑C盘红了怎么清理_Windows10系统盘深度瘦身指南  c# 在ASP.NET Core中管理和取消后台任务  如何使用Golang管理模块版本_Golanggo mod tidy与升级方法  Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数  php中作用域操作符能访问私有静态属性吗_访问权限限制【指南】  Mac如何设置动态壁纸?(让桌面动起来)  Windows10电脑怎么设置虚拟内存_Win10高级系统设置性能  如何使用Golang搭建本地API测试环境_快速验证接口功能  Win11怎么设置任务栏图标大小_Windows11注册表TaskbarSi修改  如何在 Go 中正确测试带 Cookie 的 HTTP 请求  PHP主流架构如何处理会话管理_Session与Cookie【技巧】  Win11怎么清理C盘OneDrive缓存_Win11清理OneDrive缓存技巧【方法】  php条件判断怎么写_ifelse和switchcase的使用区别【对比】  Python包结构设计_大型项目组织解析【指导】  LINUX怎么设置系统语言_LINUX修改中文环境  PHP的FastAdmin架构适合二次开发吗_特点分析【介绍】  Go 语言标准库为何不提供泛型切片的 Contains 方法?  mac怎么安装字体_MAC添加第三方字体与字体册管理【教程】  Win11如何卸载OneDrive_Win11卸载OneDrive方法【教程】  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康 

 2025-12-29

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.