Question about RAII.

Walter Bright newshound at digitalmars.com
Tue Jul 4 19:47:07 PDT 2006


Peter C. Chapin wrote:
> Hello! I'm a C++ programmer who has started to look at D. I appreciate 
> many of D's design decisions. However, I'm a little confused about how 
> RAII is supported. It seems like it only semi-works. Consider the 
> function below ('Example' is some class):
> 
> Example g()
> {
>   auto Example object1 = new Example;
>   auto Example object2 = new Example;
>   Example object3;
> 
>   if (f()) {
>     object3 = object1;
>   }
>   else {
>     object3 = object2;
>   }
>   return object3;
> }
> 
> The idea is that I want to return one of two local objects depending on 
> what f() returns. Assume f() interacts with the user so its return value 
> can't be known to the compiler. The object that is not returned must be 
> cleaned up. Assume that it holds resources other than memory that need 
> to be released.
> 
> In the example above it looks like both object1 and object2 are 
> destroyed and thus the returned reference is invalid. However, if I 
> remove 'auto' from the local declarations than object1 and object2 don't 
> get destroyed until garbage collection time... which is too late. It 
> looks like I'm left with explicitly deleting the object that I don't 
> return, but this is manual resource management and not RAII.
> 
> To make this example more concrete, suppose the class in question 
> represents an on-screen window. Function g() lets the user select one of 
> two newly created windows, returning the window selected and removing 
> the other from the screen.
> 
> Thanks in advance for any comments.

The reason the example "works" in C++ is not because RAII is any 
different in D - in D, as well as C++, both object1 and object2 get 
destroyed at the end of the return. What happens in C++ is the:
	object3 = object1;
makes a *copy* of object1 via the default (or explicit) copy 
constructor. In D, just a reference to object1's instance is copied.

You can make the D version behave like the C++ one as follows:

Example g()
{
   auto Example object1 = new Example;
   auto Example object2 = new Example;
   Example object3;

   if (f()) {
     object3 = new Example(object1);
   }
   else {
     object3 = new Example(object2);
   }
   return object3;
}

and then in the definition of Example, add the constructor:

	this(Example e)
	{
		...copy members...
	}

To explicitly run the destructor on an object, use:
	delete object1;



More information about the Digitalmars-d mailing list