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