C++ 中异常安全性的不同保证级别

2025 年 2 月 11 日 | 阅读 4 分钟

C++ 编程的一个关键组成部分是异常安全,它对于在发生异常时保持代码的一致性和可靠性是必要的。在本文中,我们将阐明不同级别的异常安全和推荐实践,并探讨异常安全。

健壮的 C++ 编程需要异常安全,它确保即使在出现异常时,代码也能保持一致的行为并维护其完整性。它包括以下三个级别的保证:

  • 基本异常安全
  • 强异常安全
  • 不抛出保证

1. 基本异常安全

在此阶段,没有资源泄漏,程序保持运行,但未完成的操作可能会产生一些副作用。

示例

让我们以一个例子来说明 C++ 中的基本异常安全。

输出

 
Exception: Failed to open the File.   

说明

此代码演示了 C++ 的基本异常安全概念。"output.txt" 文件尝试使用 openFileAndPrinting() 方法打开以进行写入。如果文件无法打开,则文件会抛出 std::runtime_error。之后,构造了一个内部结构 FileCloser,它使用 RAII 在销毁时关闭文件,以确保正确的资源管理。FileCloser 对象确保在函数退出时(无论是由于成功还是异常)文件都被关闭。之后,信息被写入文件,这可能会导致异常。接下来,main() 方法在一个 try-catch 块中被调用,以处理任何异常。如果发生异常,错误消息将显示到标准错误流。此方法确保正确关闭文件,维护程序的稳定性并防止资源泄漏。

2. 强异常安全

此级别的异常安全提供更高的可靠性。如果引发异常,它会确保资源得到适当释放,并且程序的状态保持不变,就好像操作从未发生过一样。

示例

让我们以一个例子来说明 C++ 中的强异常安全。

输出

 
Error opening file: Failed to open the File.   

说明

此代码演示了 C++ 的基本异常安全。尝试通过 openFileAndPrint() 方法打开文件 "output.txt" 进行写入。如果文件无法打开,程序会抛出带有适当错误消息的 std::runtime_error。之后,文本 "Hello, Exception Safety!" 被写入文件。类似地,readFile() 方法在尝试打开同一文件进行读取后,从文件中获取每一行并将其输出到控制台。如果文件无法打开以进行读取,则会抛出 std::runtime_error。

readFile() 和 openFileAndPrint() 都被调用在 main() 方法的 try-catch 块中。如果任何函数抛出异常,则会捕获并正确处理该异常。如果 openFileAndPrint() 引发异常,则似乎存在打开文件的问题。如果 readFile() 产生异常,则表示读取文件存在问题。

通过为每个函数调用使用不同的 try-catch 块,代码提供了基本的异常安全,确保异常被捕获并正确处理。此外,由于当 std::ofstream 和 std::ifstream 对象离开其作用域时,文件会立即通过 RAII(资源获取即初始化)原则关闭,因此避免了资源泄漏。

3. 不抛出保证

在此最高级别,函数保证不抛出异常。它确保程序的资源和状态继续得到保留,即使在异常情况下也是如此。