4 Pregunta: Tutorial de RAII para C ++ [cerrado]

pregunta creada en Fri, Aug 16, 2013 12:00 AM

Me gustaría aprender a usar RAII en c ++. Creo que sé lo que es, pero no tengo idea de cómo implementarlo en mis programas. Una búsqueda rápida en Google no mostró ningún tutorial agradable.

¿Alguien tiene algún enlace agradable para enseñarme RAII?

    
32
  1. No es un enlace externo, pero puede encontrar algunas respuestas agradables aquí: stackoverflow.com/questions/395123/raii-and-smart-pointers-in-c
    2010-04-14 08: 28: 13Z
  2. @ Naveen: gracias, esa no apareció en mis enlaces cuando escribí mi título
    2010-04-14 08: 29: 01Z
  3. @ Joe Bloggs: Yo uso Google con el sitio: stackoverflow.com. Produce resultados mucho mejores.
    2010-04-14 08: 30: 06Z
  4. ¿Qué libro de texto de C ++ está utilizando que no cubre esto?
    2010-04-14 08: 36: 36Z
  5. @ Joe Bueno, ahí está tu problema. No puede aprender C ++ de los recursos en línea, necesita leer al menos un libro (de hecho, varios). Recomiendo C ++ acelerado, pero puede obtener opiniones sobre otros en stackoverflow.com/questions/388242/… . Y RAII es básico, no avanzado.
    2010-04-14 08: 50: 47Z
4 Respuestas                              4                         

No hay nada que hacer (es decir, no creo que necesites un tutorial completo).

RAII se puede explicar brevemente como "Todo recurso que requiera limpieza debe asignarse al constructor de un objeto".

En otras palabras:

Los punteros deben encapsularse en clases de puntero inteligente (consulte std :: auto_ptr, boost :: shared_ptr y boost :: scoped_ptr para ver ejemplos).

Las manijas que requieren limpieza deben encapsularse en clases que liberen /liberen automáticamente las manijas al destruirse.

La sincronización debe basarse en la liberación de la primitiva mutex /sincronización al salir del alcance (consulte el ejemplo de boost :: mutex :: scoped_lock).

No creo que realmente puedas tener un tutorial sobre RAII (no más de lo que puedes tener sobre patrones de diseño, por ejemplo). RAII es más una forma de ver los recursos que cualquier otra cosa.

Por ejemplo, en este momento estoy codificando usando WinAPI y escribí la siguiente clase:

 
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;

Esta clase no incluye la semántica de asignación y copia (los eliminé para proporcionar un ejemplo mínimo), por lo que, al devolver el valor, los controles se cerrarán dos veces.

Así es como se usa:

declaración de clase:

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

Este miembro está asignado, pero nunca llamo al ::CloseWindow(_window._handle) explícitamente (se llamará cuando las instancias del Something queden fuera del alcance (como Something::~Something - > WindowHandle::WindowHandle - > ::Close(_window._value)).

    
27
2013-10-17 16: 49: 21Z
  1. Esto también se puede lograr usando boost::shared_ptr con un desasignador personalizado. Por ejemplo, boost::shared_ptr<void> checked_handle( open_some_handle(), boost::bind< void >( &::CloseHandle, _1 ) );
    2010-04-14 21: 40: 05Z
  2. Buen punto, pero lo escribiría con algo de tipificación al menos. No me gusta mucho usar una clase llamada "shared_ptr" para algo más que un puntero. Conduce a desordenar el camino en mantenimiento.
    2010-04-26 15: 12: 13Z
  3. En cierto sentido, una manole es un puntero. Es una representación de algún recurso que usa un tipo de datos primitivo (es decir, apunta a un recurso que usa un entero, generalmente).
    2013-08-16 15: 50: 03Z

La wikipedia no está mal.

    
3
2010-04-14 08: 28: 57Z

La referencia que personalmente he encontrado más útil sobre el tema de RAII es el libro Excepcional C ++ por Herb Sutter.

Muchos de los temas tratados en ese libro se mencionan en los artículos del gurú de la semana de Sutter. Esos artículos están disponibles en http://gotw.ca/gotw/index.htm .     

2
2010-04-14 08: 47: 17Z
  1. ¿Qué capítulo de Exceptional C ++ trata el tema de RAII?
    2011-02-17 14: 57: 16Z

El artículo 13 de "E + C + efectivo también es bastante útil

    
2
2010-09-24 05: 48: 56Z
fuente colocada aquí
Otras preguntas