web-dev-qa-db-ja.com

C ++用のRAIIチュートリアル

C++でRAIIを使用する方法を学びたいのですが。私はそれが何であるかを知っていると思いますが、私のプログラムにそれを実装する方法がわかりません。クイックグーグル検索はニースのチュートリアルを表示しませんでした。

RAIIを教えてくれる素敵なリンクはありますか?

36
Joe Bloggs

それには何もありません(つまり、完全なチュートリアルは必要ないと思います)。

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;
_

このクラスには割り当てとコピーのセマンティクスが含まれていないため(最小限の例を提供するために削除しました)、値で返すと、ハンドルが2回閉じられます。

使用方法は次のとおりです。

クラス宣言:

_class Something
{
public:
    // ...
private:
    WindowHandle        _window;
};
_

このメンバーは割り当てられていますが、明示的に::CloseWindow(_window._handle)を呼び出すことはありません(Somethingのインスタンスがスコープ外になると呼び出されます(_Something::~Something_-> _WindowHandle::WindowHandle_-> ::Close(_window._value) )。

29
utnapistim

wikipedia 説明は悪くありません。

3
Goz

"Effective C +" のアイテム13もかなり便利です

2
Chubsdad

私が個人的にRAIIのトピックに関して最も役立つと思った参考文献は、Herb Sutterによる本 Exceptional C++ です。

この本で取り上げられているトピックの多くは、SutterによるGuru of the Weekの記事で触れられています。これらの記事は http://gotw.ca/gotw/index.htm で入手できます。

2