C++ RAII 教程

发布于 2024-08-29 00:25:14 字数 1536 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ら栖息 2024-09-05 00:25:14

没有什么(也就是说,我认为你不需要完整的教程)。

RAII 可以简单地解释为“每个需要清理的资源都应该交给对象的构造函数”。

换句话说:

指针应该封装在智能指针类中(例如,参见 std::auto_ptr、boost::shared_ptr 和 boost::scoped_ptr)。

需要清理的句柄应该封装在类中,在销毁时自动释放/释放句柄。

同步应该依赖于作用域退出时释放互斥/同步原语(有关示例,请参阅 boost::mutex::scoped_lock 用法)。

我不认为您真的可以拥有有关 RAII 的教程(例如,您无法拥有有关设计模式的教程)。 RAII 更多的是一种查看资源的方式。

例如,目前我正在使用 WinAPI 进行编码,并且编写了以下类:

template<typename H, BOOL _stdcall CloseFunction(H)>
class checked_handle
{
public:
    typedef checked_handle<H,CloseFunction> MyType;
    typedef typename H HandleType;

    static const HandleType     NoValue;

    checked_handle(const HandleType value)
        : _value(value)
    {
    }

    ~checked_handle()
    {
        Close();
    }

    HandleType* operator &()
    {
        return &_value;
    }

    operator HandleType()
    {
        return _value;
    }

private:
    HandleType      _value;

    void Close(const HandleType newValue = NoValue)
    {
        CloseFunction(_value);
        _value = newValue;
    }
};

template<typename H,BOOL _stdcall CloseFunction(H)>
const typename checked_handle<H,CloseFunction>::HandleType 
    checked_handle<H,CloseFunction>::NoValue = 
    checked_handle<H,CloseFunction>::HandleType(INVALID_HANDLE_VALUE);

typedef checked_handle<HANDLE,::CloseHandle> CheckedHandle;
typedef checked_handle<HWINSTA,::CloseWindowStation> WinStationHandle;
typedef checked_handle<HDESK,::CloseDesktop> DesktopHandle;
typedef checked_handle<HDEVNOTIFY,::UnregisterDeviceNotification> DevNotifyHandle;
typedef checked_handle<HWND,::DestroyWindow> WindowHandle;

BOOL __stdcall CloseKey(HKEY hKey);
typedef checked_handle<HKEY,CloseKey> RegHandle;

该类不包括赋值和复制语义(我删除了它们以提供一个最小的示例),因此按值返回将导致句柄关闭了两次。

它的使用方式如下:

类声明:

class Something
{
public:
    // ...
private:
    WindowHandle        _window;
};

该成员已分配,但我从不显式调用 ::CloseWindow(_window._handle) (当 Something 实例消失时,它将被调用范围(如 Something::~Something -> WindowHandle::WindowHandle -> ::Close(_window._value) )。

There's nothing to it (that is, I don't think you need a full tutorial).

RAII can be shortly explained as "Every resource requiring cleanup should be given to an object's constructor."

In other words:

Pointers should be encapsulated in smart pointer classes (see std::auto_ptr, boost::shared_ptr and boost::scoped_ptr for examples).

Handles requiring cleanup should be encapsulated in classes that automatically free/release the handles upon destruction.

Synchronization should rely on releasing the mutex/synchronization primitive upon scope exit (see boost::mutex::scoped_lock usage for an example).

I don't think you can really have a tutorial on RAII (not anymore than you can have one on design patterns for example). RAII is more of a way of looking at resources than anything else.

For example, at the moment I'm coding using WinAPI and I wrote the following class:

template<typename H, BOOL _stdcall CloseFunction(H)>
class checked_handle
{
public:
    typedef checked_handle<H,CloseFunction> MyType;
    typedef typename H HandleType;

    static const HandleType     NoValue;

    checked_handle(const HandleType value)
        : _value(value)
    {
    }

    ~checked_handle()
    {
        Close();
    }

    HandleType* operator &()
    {
        return &_value;
    }

    operator HandleType()
    {
        return _value;
    }

private:
    HandleType      _value;

    void Close(const HandleType newValue = NoValue)
    {
        CloseFunction(_value);
        _value = newValue;
    }
};

template<typename H,BOOL _stdcall CloseFunction(H)>
const typename checked_handle<H,CloseFunction>::HandleType 
    checked_handle<H,CloseFunction>::NoValue = 
    checked_handle<H,CloseFunction>::HandleType(INVALID_HANDLE_VALUE);

typedef checked_handle<HANDLE,::CloseHandle> CheckedHandle;
typedef checked_handle<HWINSTA,::CloseWindowStation> WinStationHandle;
typedef checked_handle<HDESK,::CloseDesktop> DesktopHandle;
typedef checked_handle<HDEVNOTIFY,::UnregisterDeviceNotification> DevNotifyHandle;
typedef checked_handle<HWND,::DestroyWindow> WindowHandle;

BOOL __stdcall CloseKey(HKEY hKey);
typedef checked_handle<HKEY,CloseKey> RegHandle;

This class doesn't include assignment and copy semantics (I removed them to provide a minimal example) so returning by value, will cause the handles to be closed twice.

Here's how it's used:

class declaration:

class Something
{
public:
    // ...
private:
    WindowHandle        _window;
};

This member is allocated but I never call ::CloseWindow(_window._handle) explicitely (it will be called when instances of Something go out of scope (as Something::~Something -> WindowHandle::WindowHandle -> ::Close(_window._value) ).

半衬遮猫 2024-09-05 00:25:14

wikipedia 的解释还不错。

The wikipedia explanation isn't bad.

浸婚纱 2024-09-05 00:25:14

我个人发现关于 RAII 主题最有帮助的参考文献是Exceptional C++< /a> 作者:赫伯·萨特。

萨特的《本周大师》文章中涉及到该书中涵盖的许多主题。这些文章可在 http://gotw.ca/gotw/index.htm 上找到。

The reference that I personally have found most helpful on the topic of RAII is the book Exceptional C++ by Herb Sutter.

Many of the topics covered in that book are touched on in the Guru of the Week articles by Sutter. Those articles are available at http://gotw.ca/gotw/index.htm.

怪异←思 2024-09-05 00:25:14

“有效的 C+” 的第 13 项也非常有用

Item 13 of "Effective C+" is also pretty useful

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文