C++ 是否支持“finally"块?(我一直听到的这个“RAII"是什么?)

2021-12-17 00:00:00 exception c++ finally c++-faq raii

C++ 是否支持终于' 块?

Does C++ support 'finally' blocks?

什么是RAII 惯用语?

C++'s RAII idiom 和 C#'s '有什么区别using'语句?

What is the difference between C++'s RAII idiom and C#'s 'using' statement?

推荐答案

不,C++ 不支持finally"块.原因是 C++ 转而支持 RAII:资源获取即初始化"――一个糟糕的名字? 一个真正有用的概念.

No, C++ does not support 'finally' blocks. The reason is that C++ instead supports RAII: "Resource Acquisition Is Initialization" -- a poor name? for a really useful concept.

这个想法是一个对象的析构函数负责释放资源.当对象具有自动存储持续时间时,对象的析构函数将在创建它的块退出时调用――即使该块在存在异常的情况下退出.这是Bjarne Stroustrup 对该主题的解释.

The idea is that an object's destructor is responsible for freeing resources. When the object has automatic storage duration, the object's destructor will be called when the block in which it was created exits -- even when that block is exited in the presence of an exception. Here is Bjarne Stroustrup's explanation of the topic.

RAII 的一个常见用途是锁定互斥锁:

A common use for RAII is locking a mutex:

// A class with implements RAII
class lock
{
    mutex &m_;

public:
    lock(mutex &m)
      : m_(m)
    {
        m.acquire();
    }
    ~lock()
    {
        m_.release();
    }
};

// A class which uses 'mutex' and 'lock' objects
class foo
{
    mutex mutex_; // mutex for locking 'foo' object
public:
    void bar()
    {
        lock scopeLock(mutex_); // lock object.

        foobar(); // an operation which may throw an exception

        // scopeLock will be destructed even if an exception
        // occurs, which will release the mutex and allow
        // other functions to lock the object and run.
    }
};

RAII 还简化了使用对象作为其他类的成员.当拥有的类被析构时,由 RAII 类管理的资源被释放,因为 RAII 管理的类的析构函数因此被调用.这意味着当您对管理资源的类中的所有成员使用 RAII 时,您可以使用一个非常简单的,甚至可能是默认的所有者类的析构函数,因为它不需要手动管理其成员资源生命周期.(感谢 Mike B 指出这一点.)

RAII also simplifies using objects as members of other classes. When the owning class' is destructed, the resource managed by the RAII class gets released because the destructor for the RAII-managed class gets called as a result. This means that when you use RAII for all members in a class that manage resources, you can get away with using a very simple, maybe even the default, destructor for the owner class since it doesn't need to manually manage its member resource lifetimes. (Thanks to Mike B for pointing this out.)

对于熟悉 C# 或 VB.NET 的人,您可能会认识到 RAII 类似于 .NET 确定性销毁使用 IDisposable 和 'using' 语句.确实,这两种方法非常相似.主要区别在于 RAII 将确定性地释放任何类型的资源――包括内存.在 .NET(甚至是 .NET 语言 C++/CLI)中实现 IDisposable 时,将确定性地释放除内存之外的资源.在 .NET 中,内存不是确定性地释放;内存仅在垃圾回收周期内释放.

For those familliar with C# or VB.NET, you may recognize that RAII is similar to .NET deterministic destruction using IDisposable and 'using' statements. Indeed, the two methods are very similar. The main difference is that RAII will deterministically release any type of resource -- including memory. When implementing IDisposable in .NET (even the .NET language C++/CLI), resources will be deterministically released except for memory. In .NET, memory is not deterministically released; memory is only released during garbage collection cycles.

 

? 有些人认为破坏就是资源放弃"是 RAII 习语的更准确名称.

? Some people believe that "Destruction is Resource Relinquishment" is a more accurate name for the RAII idiom.

相关文章