Recommended way to do RAII cleanly

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Sun Jul 11 23:41:21 PDT 2010


On Sun, 11 Jul 2010 23:25:32 -0700, Jonathan M Davis wrote:

> Okay. There are cases where you want a constructor to do something when
> the class/struct is created, and you want the destructor to do something
> when the class/struct goes out of scope. A classic example would be an
> autolock for a mutex. Another would be the hourglass in MFC - it's
> displayed when the object is created and disappears when the object is
> destroyed (so all you have to do is declare the object it at the
> beggining of the function and it automatically is displayed and then
> disappears). This is classic RAII.
> 
> Obviously, because classes are reference types with infinite lifetime
> while structs are value types with their lifetime restricted to their
> scope, structs would be the better choice for RAII. I have noticed a bit
> of a snag however: structs can't have default constructors.
> 
> After reading TDPL, I completely understand that structs can't have
> default constructors due to how the init property works. However, the
> classic case where you want to simply declare an object and have it do
> what it does through RAII then falls apart. Ideally, you'd have
> something like this
> 
> struct S
> {
>     this()
>     {
>         /* do something */
>     }
> 
>     ~this()
>     {
>        /* undo what you did before or do whatever clean up is required
>        for it */
>     }
> }
> 
> void main()
> {
>     auto s = S();
>    /* whatever the rest of main() does */
> }
> 
> 
> Thanks to the lack of default constructor, you can't do that. Therefore,
> I see 2 options:
> 
> 1.  Create a nonsensical constructor that takes an argument of _some_
> kind which is totally ignored.
> 
> 2. Create a factory function to create the struct, and it does whatever
> would have been in the default constructor.
> 
> 
> Out of those two options, the second seems the best, but it seems to me
> that there have got to be more options than that. So, the question is
> what would be the best option (be it one of those or another that I
> haven't though of) to do RAII in the general case? What would be "best
> practice" for D when dealing with structs intended for RAII without any
> arguments to their constructor when you can't have a default
> constructor?


I'd say option 2 is your best bet.  I don't know any other way to "fake" 
default construction.

That said, the recommended best practice for D is, if possible, to use 
scope guards:

  void doStuffWith(string resourceName)
  {
      auto resource = acquire(resourceName);
      scope(exit) release(resource);

      ... // Do stuff with resource here
  }

-Lars


More information about the Digitalmars-d-learn mailing list