为什么C++没有finally

本文介绍C++中如何使用资源获得即初始化(RAII)技术管理资源,避免资源泄漏。通过实例展示了如何创建资源句柄类实现自动资源管理。

第一部分

        标准 C++ 是没有类似 finally 这样的语句结构的。C# / Java 中保证无论是否出现异常,finally block 的代码均会得到执行;而 C++ 中,不论是否出现异常,局部变量的析构函数是会保证执行的,所以相对应与 finally block,C++ 的解决办法是 RAII。

        在C++中通常使用RAII,即Resource Aquisition Is Initialization.就是将资源封装成一个类,将资源的初始化封装在构造函数里,释放封装在析构函数里。要在局部使用资源的时候,就实例化一个local object。在抛出异常的时候,由于local object脱离了作用域,自动调用析构函数,会保证资源被释放。


第二部分

因为C++提供了另外一种方法,它几乎总是更好的:“资源获得即初始化”(resourceacquisiton is initialization)技术。基本的思路是,通过一个局部对象来表现资源,于是局部对象的析构函数将会释放资源。这样,程序员就不会忘记释放资源了。举例来说:
class File_handle {
    FILE* p;
    public:
    File_handle(const char* n, const char* a)
    { p = fopen(n,a); if (p==0) throw Open_error(errno); }
    File_handle(FILE* pp)
    { p = pp; if (p==0) throw Open_error(errno); }
    ~File_handle() { fclose(p); }
    operator FILE*() { return p; }
    // ...
};
void f(const char* fn){
    File_handle f(fn,"rw"); //打开fn 进行读写
    // 通过f 使用文件
}

在一个系统中,需要为每一个资源都使用一个“资源句柄”类。无论如何,我们不需要为每一个资源获得都写出“finally”语句。在实时系统中,资源获得要远远多于资源的种类,因此和使用“finally”构造相比,“资源获得即初始化”技术会产生少得多的代码。

C++ 有 `try` 和 `catch` 机制,但没有像 C#、Java 那样标准的 `finally` 机制。 `try` 和 `catch` 机制用于异常处理。`try` 块中放置可能抛出异常的代码,`catch` 块用于捕获并处理这些异常。以下是一个简单的示例: ```cpp #include <iostream> int main() { try { int num1 = 10; int num2 = 0; if (num2 == 0) { throw std::runtime_error("Division by zero!"); } int result = num1 / num2; std::cout << "Result: " << result << std::endl; } catch (const std::exception& e) { std::cerr << "Exception caught: " << e.what() << std::endl; } return 0; } ``` 在上述代码中,`try` 块中进行除法运算,若除数为 0 则抛出 `std::runtime_error` 异常,`catch` 块捕获该异常并输出错误信息。 虽然 C++ 没有标准的 `finally` 机制,但可以通过 RAII(资源获取即初始化)技术来实现类似 `finally` 的功能。RAII 是 C++ 中管理资源的一种方式,通过在对象的构造函数中获取资源,在析构函数中释放资源,确保资源在对象生命周期结束时被正确释放。以下是一个使用 RAII 实现类似 `finally` 功能的示例: ```cpp #include <iostream> class Finally { public: explicit Finally(std::function<void()> func) : func_(std::move(func)) {} ~Finally() { func_(); } private: std::function<void()> func_; }; int main() { try { std::cout << "Inside try block" << std::endl; auto finally = Finally([]() { std::cout << "Finally block executed" << std::endl; }); throw std::runtime_error("Exception thrown"); } catch (const std::exception& e) { std::cerr << "Exception caught: " << e.what() << std::endl; } return 0; } ``` 在这个示例中,`Finally` 类的构造函数接受一个函数对象,析构函数中调用该函数对象。在 `try` 块中创建 `Finally` 对象,无论 `try` 块中是否抛出异常,`Finally` 对象的析构函数都会在离开作用域时被调用,从而实现类似 `finally` 的功能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值