C++ 错误处理:try/catch 与高级技术

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++ 错误处理:从 try/catch 到现代方法

\n\n

C++ 中的异常机制是一个强大但需要深入理解的工具。虽然大多数开发者都知道 try/catch 的基本用法,但专业的错误处理包含的内容远不止于此:从异常安全保证到无异常的替代策略。在本文中,我们将深入探讨现代 C++ 中的高级错误处理技术。

\n\n

1. 异常安全保证:可靠代码的基石

\n\n

任何可能抛出异常的函数都必须提供以下三种安全保证之一:

\n\n
    \n
  • 基本保证 (Basic Guarantee): 发生异常时,对象的不变量得以保持,且无资源泄漏。对象可能处于不可预测但有效的状态。
  • \n
  • 强保证 (Strong Guarantee): 操作要么完全成功,要么程序状态保持不变(原子性)。通过 copy-and-swap 惯用法实现。
  • \n
  • 无异常保证 (Noexcept Guarantee): 函数永远不会抛出异常。对于析构函数、移动操作以及容器中使用的操作至关重要。
  • \n
\n\n
// 通过 copy-and-swap 实现强保证的示例\nclass Vector {\n    int* data;\n    size_t sz, cap;\npublic:\n    void push_back(int value) {\n        if (sz == cap) {\n            // 1. 创建副本\n            Vector tmp(*this);\n            // 2. 修改副本(可能抛出异常)\n            tmp.reserve(cap * 2);\n            // 3. 交换 (noexcept!)\n            swap(tmp);\n        }\n        data[sz++] = value;  // noexcept\n    }\n    \n    void swap(Vector& other) noexcept {\n        std::swap(data, other.data);\n        std::swap(sz, other.sz);\n        std::swap(cap, other.cap);\n    }\n};
\n\n

2. RAII:资源管理的基础

\n\n

RAII(资源获取即初始化) 惯用法不仅仅是智能指针。它是一个基本原则,有助于避免异常情况下的资源泄漏:

\n\n
    \n
  • 资源在构造函数中获取
  • \n
  • 在析构函数中释放(默认是 noexcept)
  • \n
  • 在析构函数中抛出异常会导致未定义行为 (UB)
  • \n
\n\n
// 文件描述符的 RAII 包装器\nclass FileDescriptor {\n    int fd;\npublic:\n    explicit FileDescriptor(const char* path) \n        : fd(open(path, O_RDONLY)) {\n        if (fd == -1) throw std::runtime_error("Failed to open file");\n    }\n    \n    ~FileDescriptor() noexcept {\n        if (fd != -1) close(fd);\n    }\n    \n    // 禁止复制,允许移动\n    FileDescriptor(FileDescriptor&& other) noexcept : fd(other.fd) {\n        other.fd = -1;\n    }\n};
\n\n

3. 异常的现代替代方案:std::optional 和 std::expected

\n\n

并非所有错误都应通过异常处理。对于预期错误(如无效输入、数据缺失),最好使用包装类型:

\n\n
#include <optional>\n#include <expected>  // C++23\n\n// std::optional — 用于可选值\nstd::optional<int> safe_divide(int a, int b) {\n    if (b == 0) return std::nullopt;\n    return a / b;\n}\n\n// std::expected — 用于包含信息的错误 (C++23)\nstd::expected<double, std::string> sqrt_checked(double x) {\n    if (x < 0) return std::unexpected("Negative input");\n    return std::sqrt(x);\n}\n\n// 使用示例\nauto result = safe_divide(10, 0);\nif (result) {\n    std::cout << *result;\n} else {\n    std::cout << "Division by zero";\n}
\n\n

4. noexcept:规范与优化

\n\n

noexcept 说明符不仅仅是文档。它会影响性能,并且

博客

书籍推荐