digitalmars.D - Reset class member variables
- mandel (27/27) Sep 07 2007 Hi,
- Matti Niemenmaa (4/35) Sep 07 2007 Does "this = new typeof(this);" work?
- Sean Kelly (16/47) Sep 07 2007 It's a bit horrifying, but this should work:
- mandel (3/47) Sep 07 2007 [..]
- mandel (4/24) Sep 07 2007 Ok, I jumped to early. :/
- Sean Kelly (9/12) Sep 07 2007 Hrm... to deal with that I think you'd have to use foreach and tupleof,
- mandel (6/33) Sep 07 2007 No, it does have no effect.
- dennis luehring (6/14) Sep 07 2007 what about creating a new object everytime you need a fresh one?
- dennis luehring (24/25) Sep 07 2007 examples:
- mandel (8/24) Sep 07 2007 I agree, in many cases it is a design problem
- Nathan Reed (11/12) Sep 07 2007 In a garbage collected language like D, allocations are extremely fast,
- Sean Kelly (13/25) Sep 08 2007 Or if there's some reason that the object must be re-initialized in
- Daniel Keep (19/34) Sep 08 2007 Or you might just be dealing with thousands of frequently created and
- Sean Kelly (3/8) Sep 09 2007 It's possible to use 'new' for structs too :-p
- Ingo Oeser (10/20) Sep 09 2007 Just to support Seans argument here...
- Regan Heath (30/61) Sep 10 2007 How about putting the member variables you want to reset inside a struct...
Hi, I have some big classes with lots of member variables that need to be reset to theire initial value. Therefore I thought about a more reliable way to accomplish this, because it's hard to keep track of variables I have added. It also looks bloated to assign all values manually. class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { scope tmp = new typeof(this); foreach(i, x; tmp.tupleof) { this.tupleof[i] = x; } } } The problem is that I have to avoid to try to set const values and static arrays. How can this be done?
Sep 07 2007
mandel wrote:Hi, I have some big classes with lots of member variables that need to be reset to theire initial value. Therefore I thought about a more reliable way to accomplish this, because it's hard to keep track of variables I have added. It also looks bloated to assign all values manually. class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { scope tmp = new typeof(this); foreach(i, x; tmp.tupleof) { this.tupleof[i] = x; } } } The problem is that I have to avoid to try to set const values and static arrays. How can this be done?Does "this = new typeof(this);" work? -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Sep 07 2007
mandel wrote:Hi, I have some big classes with lots of member variables that need to be reset to theire initial value. Therefore I thought about a more reliable way to accomplish this, because it's hard to keep track of variables I have added. It also looks bloated to assign all values manually. class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { scope tmp = new typeof(this); foreach(i, x; tmp.tupleof) { this.tupleof[i] = x; } } } The problem is that I have to avoid to try to set const values and static arrays. How can this be done?It's a bit horrifying, but this should work: class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { (cast(byte*) this)[0 .. this.classinfo.init.length] = this.classinfo.init[0 .. $]; } } Sean
Sep 07 2007
Yes ,that works (and looks horrific, too). :P Sean Kelly Wrote:mandel wrote:[..]Hi,class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { scope tmp = new typeof(this); foreach(i, x; tmp.tupleof) { this.tupleof[i] = x; } } } The problem is that I have to avoid to try to set const values and static arrays. How can this be done?It's a bit horrifying, but this should work: class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { (cast(byte*) this)[0 .. this.classinfo.init.length] = this.classinfo.init[0 .. $]; } } Sean
Sep 07 2007
Ok, I jumped to early. :/ This method ignores const values that I have set in the ctor: So, "this() { y = 123; }" would be reset to 0. Sean Kelly Wrote:It's a bit horrifying, but this should work: class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { (cast(byte*) this)[0 .. this.classinfo.init.length] = this.classinfo.init[0 .. $]; } } Sean
Sep 07 2007
mandel wrote:Ok, I jumped to early. :/ This method ignores const values that I have set in the ctor: So, "this() { y = 123; }" would be reset to 0.Hrm... to deal with that I think you'd have to use foreach and tupleof, but I don't think D 1.0 provides a means for detecting the storage type of a declaration. Ideally, you'd want to do something like this: foreach( pos, inout val; this.tupleof ) { static if( !is( typeof( val ) : const ) ) val = this.classinfo.init.tupleof[pos]; }
Sep 07 2007
Matti Niemenmaa Wrote:mandel wrote:[..]Hi,No, it does have no effect. Btw.: that's the error message I get from dmd: Error: can only initialize const member y inside constructor Error: cannot assign to static array this.bufferclass Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { scope tmp = new typeof(this); foreach(i, x; tmp.tupleof) { this.tupleof[i] = x; } } } The problem is that I have to avoid to try to set const values and static arrays. How can this be done?Does "this = new typeof(this);" work?
Sep 07 2007
mandel schrieb:Hi, I have some big classes with lots of member variables that need to be reset to theire initial value. Therefore I thought about a more reliable way to accomplish this, because it's hard to keep track of variables I have added. It also looks bloated to assign all values manually.what about creating a new object everytime you need a fresh one? i think that new is faster than reinitalise all members - and you get rid of your track problems (btw: the need of reseting an object could be a design problem) ciao dennis
Sep 07 2007
(btw: the need of reseting an object could be a design problem)examples: int result[]; auto obj = new TheObject(); for( ... ) { result ~= obj.do_some_thing( some_data ); obj.reset(); } possible errors: you forgot the .reset() or the reset isn't correct implemented .... int result[]; for( ... ) { auto obj = new TheObject(); result ~= obj.do_some_thing( some_data ); } in this case you don't have to safe/repair your object state possible errors: none --- design blabla the obj.reset is (maybe) an hard optimizing step (if the newing IS expensive) or your obj is doing the wrong stuff (in the wrong context?)
Sep 07 2007
I agree, in many cases it is a design problem to reset an Object because the problems introduced by it often outweights the speed/memory overhead. But it's nice when the initializing problem can be done in a foolproof way. It's nice not to have to sacrifice speed for reliability. dennis luehring Wrote:mandel schrieb:Hi, I have some big classes with lots of member variables that need to be reset to theire initial value. Therefore I thought about a more reliable way to accomplish this, because it's hard to keep track of variables I have added. It also looks bloated to assign all values manually.what about creating a new object everytime you need a fresh one? i think that new is faster than reinitalise all members - and you get rid of your track problems (btw: the need of reseting an object could be a design problem) ciao dennis
Sep 07 2007
mandel wrote:It's nice not to have to sacrifice speed for reliability.In a garbage collected language like D, allocations are extremely fast, potentially several times faster than heap based languages like C/C++. Using a new instance of the object for each iteration of the loop is really what you're doing /conceptually/, anyway...so, I wouldn't worry about the allocation performance too much unless you've profiled the app and established that it is a bottleneck. And if that's the case you might want to think about making the object a struct (so a value-type, allocated on the stack) anyway. Thanks, Nathan Reed
Sep 07 2007
Nathan Reed wrote:mandel wrote:Or if there's some reason that the object must be re-initialized in place--say, to preserve its address. One could argue that this necessity indicates a poor program design, but I imagine there are cases where it may apply. For what it's worth, this would be quite easy to accomplish if D supported placement new as a default construction method (rather than requiring the user to override operator new to do so). Then, re-initializing an object would be as simple as: this = new(this) typeof(this); (assuming the runtime doesn't do anything too weird in _d_new)It's nice not to have to sacrifice speed for reliability.In a garbage collected language like D, allocations are extremely fast, potentially several times faster than heap based languages like C/C++. Using a new instance of the object for each iteration of the loop is really what you're doing /conceptually/, anyway...so, I wouldn't worry about the allocation performance too much unless you've profiled the app and established that it is a bottleneck.And if that's the case you might want to think about making the object a struct (so a value-type, allocated on the stack) anyway.Good point. Sean
Sep 08 2007
Sean Kelly wrote:[snip] Or if there's some reason that the object must be re-initialized in place--say, to preserve its address. One could argue that this necessity indicates a poor program design, but I imagine there are cases where it may apply.Or you might just be dealing with thousands of frequently created and destroyed tiny, tiny objects and yes the overhead of allocating/deallocating *is* an issue. Like pretty sparkly particles -- free lists are your friend! :)For what it's worth, this would be quite easy to accomplish if D supported placement new as a default construction method (rather than requiring the user to override operator new to do so). Then, re-initializing an object would be as simple as: this = new(this) typeof(this); (assuming the runtime doesn't do anything too weird in _d_new)That makes me uneasy because then you can't overload new(void*) for anything. Maybe... void* inplace(TypeInfo ti, size_t size, void* custom_arg) { return custom_arg; } this = new.inplace(this) typeof(this); So make a special case of the unified function call syntax such that if you have a function whose first two arguments are (TypeInfo,size_t), then it can be called as a "member" of new. This allows classes to override new as necessary, whilst still providing a way to do more general overloads.Sorry, pretty sparkly particles must persist across stack frames :( -- DanielAnd if that's the case you might want to think about making the object a struct (so a value-type, allocated on the stack) anyway.
Sep 08 2007
Daniel Keep wrote:It's possible to use 'new' for structs too :-p SeanSorry, pretty sparkly particles must persist across stack frames :(And if that's the case you might want to think about making the object a struct (so a value-type, allocated on the stack) anyway.
Sep 09 2007
Sean Kelly wrote:Nathan Reed wrote:Just to support Seans argument here... One example from driver development: Some on-card descriptor, you get mapped via IO memory. The class would be your driver instance for this card and your descriptor a struct or array member in that class. You have to re-initialize that descriptor or at least part of after receive. One usually does that in some cleanup run for many at once. Network Interface Cards (NICs) often work that way. Best Regards Ingo OeserUsing a new instance of the object for each iteration of the loop is really what you're doing /conceptually/, anyway...so, I wouldn't worry about the allocation performance too much unless you've profiled the app and established that it is a bottleneck.Or if there's some reason that the object must be re-initialized in place--say, to preserve its address. One could argue that this necessity indicates a poor program design, but I imagine there are cases where it may apply.
Sep 09 2007
mandel wrote:Hi, I have some big classes with lots of member variables that need to be reset to theire initial value. Therefore I thought about a more reliable way to accomplish this, because it's hard to keep track of variables I have added. It also looks bloated to assign all values manually. class Foo { uint x; char[] name = "world"; //problematic: const uint y; char[1024] buffer; void reset() { scope tmp = new typeof(this); foreach(i, x; tmp.tupleof) { this.tupleof[i] = x; } } } The problem is that I have to avoid to try to set const values and static arrays. How can this be done?How about putting the member variables you want to reset inside a struct inside the class, eg. import std.stdio; class Foo { struct FooData { int a = 6; } FooData data; int a() { return data.a; } void reset() { data = FooData.init; } } void main() { auto f = new Foo(); writefln(f.a); f.data.a = 5; writefln(f.a); f.reset(); writefln(f.a); } The proposed "alias data this" could later be used to bring the members of FooData into the scope of Foo allowing you to access them as "f.a" without property methods. Regan
Sep 10 2007