digitalmars.D - Question about RAII.
- Peter C. Chapin (34/34) Jul 04 2006 Hello! I'm a C++ programmer who has started to look at D. I appreciate
- Derek Parnell (13/17) Jul 04 2006 The 'auto' in this context means "destroy the local member when it goes ...
- Chris Nicholson-Sauls (6/47) Jul 04 2006 An auto referance such as those above is guaranteed to be destroyed at t...
- Oskar Linde (21/46) Jul 04 2006 It looks like you want some kind of transfer semantics. You can do that
- Peter C. Chapin (6/17) Jul 04 2006 That's a neat trick. Thanks. I can see that in many cases specifying whi...
- Derek Parnell (33/53) Jul 04 2006 Just checking, but doesn't setting an object reference to null just flag...
- Bruno Medeiros (12/67) Jul 04 2006 I'm not sure if you're just asking that without regards to the previous
- Derek Parnell (10/15) Jul 04 2006 Yep. I did misunderstand. My mistake, but I can see the 'trick' now. Is
- Bruno Medeiros (15/27) Jul 05 2006 Well, actually, now that I recall the spec, that behavior isn't valid:
- Sean Kelly (4/15) Jul 05 2006 The latter I think. Walter has said in the past that the compiler is
- Robert.Atkinson NOSPAM.gmail.com.NOSPAM (6/40) Jul 04 2006 Everyone's already told you that returning an auto-reference is impossib...
- Jarrett Billingsley (15/19) Jul 04 2006 You'll notice the auto reference is being assigned to a non-auto referen...
- Walter Bright (28/67) Jul 04 2006 The reason the example "works" in C++ is not because RAII is any
- Peter C. Chapin (4/20) Jul 05 2006 I see what you are saying. Thanks, that is helpful.
- Hasan Aljudy (4/12) Jul 05 2006 I always had the impression that RAII indeed *is* manual resource
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. Peter
Jul 04 2006
On Tue, 04 Jul 2006 23:05:58 +1000, Peter C. Chapin <pchapin sover.net> 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):The 'auto' in this context means "destroy the local member when it goes out of scope". This may or may not correlate to your RAII definition but that's what 'auto' means in D. It doesn't matter if the object is in use or not, if it goes out of scope it is destroyed. So in the situation you describe, you will be required to explictly delete the object you no longer want and do not use 'auto'. Of course, another method is to only create the object when you know which one to create. -- Derek Parnell Melbourne, Australia
Jul 04 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. PeterAn auto referance such as those above is guaranteed to be destroyed at the end of the scope in which it is declared. Returning such a referance is a no-no, as the object on the other side no longer exists when the function has ended! (If you had directly returned object1 or object2, you should have gotten a compile-time error I believe.) -- Chris Nicholson-Sauls
Jul 04 2006
Peter C. Chapin skrev: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; }It looks like you want some kind of transfer semantics. You can do that manually: if (f()) { object3 = object1; object1 = null; } else { object3 = object2; object2 = null; } D lacks the necessary(*) provisions that would be needed to implement such behavior automatically. (like the c++ auto_ptr)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.The both raii variables have no way of knowing if other live references to the same object exists. They are not cleared when assigned to any other reference holding variable or passed to functions etc. /Oskar *) The obvious implementations would be a pointer wrapping struct, but for this D lacks: - assignment operator (and possibly copy) overloading for structs - destructors for structs
Jul 04 2006
Oskar Linde <oskar.lindeREM OVEgmail.com> wrote in news:e8dqj5$29ns$1 digitaldaemon.com:It looks like you want some kind of transfer semantics. You can do that manually: if (f()) { object3 = object1; object1 = null; } else { object3 = object2; object2 = null; }That's a neat trick. Thanks. I can see that in many cases specifying which of the autos I don't want destroyed (in effect) would be easier than explicitly destroying everything else. Peter
Jul 04 2006
On Tue, 4 Jul 2006 17:35:55 +0000 (UTC), Peter C. Chapin wrote:Oskar Linde <oskar.lindeREM OVEgmail.com> wrote in news:e8dqj5$29ns$1 digitaldaemon.com:Just checking, but doesn't setting an object reference to null just flag it as *available* for garbage collection, and isn't there no absolute guarantee that an object will actually be collected by the GC? In which case, you can't be certain that object1 or object2 will really have their destructor called. Whereas using the delete statement ensures the destructor call. So I think that the code should be more like ... MyClass object1 = new MyClass( stuff1 ); MyClass object2 = new MyClass( stuff2 ); MyClass object3; if (f()) { object3 = object1; delete object2; } else { object3 = object2; delete object1; } Though given this simplistic example I'd actually code it more like ... MyClass object3; if (f()) { object3 = new MyClass( stuff1 ); } else { object3 = new MyClass( stuff2 ); } -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 5/07/2006 9:24:10 AMIt looks like you want some kind of transfer semantics. You can do that manually: if (f()) { object3 = object1; object1 = null; } else { object3 = object2; object2 = null; }That's a neat trick. Thanks. I can see that in many cases specifying which of the autos I don't want destroyed (in effect) would be easier than explicitly destroying everything else. Peter
Jul 04 2006
Derek Parnell wrote:On Tue, 4 Jul 2006 17:35:55 +0000 (UTC), Peter C. Chapin wrote:I'm not sure if you're just asking that without regards to the previous code, you're if asking that because you may have misunderstood the previous code. The point of setting those objects to null is not to collect it (if it was, indeed we couldn't be sure when the GC would collect), but indeed the opposite (to *prevent* collection). Because they are auto objects, the only to way to prevent (auto) collection is to setting them as null. Your example does work as well, of course.Oskar Linde <oskar.lindeREM OVEgmail.com> wrote in news:e8dqj5$29ns$1 digitaldaemon.com:Just checking, but doesn't setting an object reference to null just flag it as *available* for garbage collection, and isn't there no absolute guarantee that an object will actually be collected by the GC? In which case, you can't be certain that object1 or object2 will really have their destructor called. Whereas using the delete statement ensures the destructor call.It looks like you want some kind of transfer semantics. You can do that manually: if (f()) { object3 = object1; object1 = null; } else { object3 = object2; object2 = null; }That's a neat trick. Thanks. I can see that in many cases specifying which of the autos I don't want destroyed (in effect) would be easier than explicitly destroying everything else. PeterSo I think that the code should be more like ... MyClass object1 = new MyClass( stuff1 ); MyClass object2 = new MyClass( stuff2 ); MyClass object3; if (f()) { object3 = object1; delete object2; } else { object3 = object2; delete object1; } Though given this simplistic example I'd actually code it more like ... MyClass object3; if (f()) { object3 = new MyClass( stuff1 ); } else { object3 = new MyClass( stuff2 ); }-- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 04 2006
On Wed, 05 Jul 2006 01:36:54 +0100, Bruno Medeiros wrote:Derek Parnell wrote: I'm not sure if you're just asking that without regards to the previous code, you're if asking that because you may have misunderstood the previous code.Yep. I did misunderstand. My mistake, but I can see the 'trick' now. Is this method endorsed by Walter or is this just an artifact of the RAII implementation? -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 5/07/2006 10:43:07 AM
Jul 04 2006
Derek Parnell wrote:On Wed, 05 Jul 2006 01:36:54 +0100, Bruno Medeiros wrote:Well, actually, now that I recall the spec, that behavior isn't valid: "Assignment to an auto, other than initialization, is not allowed." But since the auto mechanism is under consideration to have some changes, the future behavior might be different and allow something like this. Or not at all. For instance, if we have an auto that instead of being applied to variables, is applied to values, like this: auto Bar(); Foo foo = auto Foo(); then how would one cancel the Foo() destruction? A new mechanism would be required, but then it might become a little awkward. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DDerek Parnell wrote: I'm not sure if you're just asking that without regards to the previous code, you're if asking that because you may have misunderstood the previous code.Yep. I did misunderstand. My mistake, but I can see the 'trick' now. Is this method endorsed by Walter or is this just an artifact of the RAII implementation?
Jul 05 2006
Derek Parnell wrote:On Wed, 05 Jul 2006 01:36:54 +0100, Bruno Medeiros wrote:The latter I think. Walter has said in the past that the compiler is free to allocate auto variables on the stack, it just isn't required. SeanDerek Parnell wrote: I'm not sure if you're just asking that without regards to the previous code, you're if asking that because you may have misunderstood the previous code.Yep. I did misunderstand. My mistake, but I can see the 'trick' now. Is this method endorsed by Walter or is this just an artifact of the RAII implementation?
Jul 05 2006
Everyone's already told you that returning an auto-reference is impossible as the reference gets destroyed by exiting the scope. Couldn't the compiler detect this and throw an compile-error? From simple inspection it seems to be a pretty easy addition to the compiler, the syntax is already quite clear. In article <Xns97F65C90D676pchapinsovernet 63.105.9.61>, Peter C. Chapin says...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. Peter
Jul 04 2006
<Robert.Atkinson NOSPAM.gmail.com.NOSPAM> wrote in message news:e8dtj3$2dc8$1 digitaldaemon.com...Couldn't the compiler detect this and throw an compile-error? From simple inspection it seems to be a pretty easy addition to the compiler, the syntax is already quite clear.You'll notice the auto reference is being assigned to a non-auto reference, which makes it all but impossible to detect. What if it were stuck into an array? What if the auto ref were passed into a function and then returned as non-auto? What if..? If you try to directly return an auto reference, the compiler will gladly whine: class Foo{} Foo foo() { auto Foo f = new Foo; return f; } dtest.d(781): escaping reference to auto local f
Jul 04 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;
Jul 04 2006
Walter Bright <newshound digitalmars.com> wrote in news:e8f9b7$17u2$1 digitaldaemon.com: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; }I see what you are saying. Thanks, that is helpful. Peter
Jul 05 2006
Peter C. Chapin wrote: <snip>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. PeterI always had the impression that RAII indeed *is* manual resource management.
Jul 05 2006