set all members to zero?
hi
is there any way to set all members (ints, float, pointers etc) to zero for a class without making a function for it? So that when i add new members they will automatically be effected by this "reset". Like:
class myClass{
int pop;
float pop2;
unit * pop3;
}
//like so
void myClass::reset(){
memResetWhatever();
}
//not simply doing it by hand:
void myClass::reset(){
pop=0;
pop2=0;
pop3=0;
}
When you start to have 30 something members of a class and all of them should be set to zero att startup you start to wish for somehting that can do it for you...
thanks
erik
Not for a class, no. More specifically, not for anything that is not POD (Plain Old Data).
For something that is POD - like a typical struct - you can do something like this:
struct MyStruct
{
// ... member
}
MyStruct a = { 0 };
Alternatively you could do memset() or ZeroMemory().
However, most classes - and definitely any class that is derived from another class - contain other data than just their members, such as vtable pointers and so forth. I'm sure that someone's going to pick holes and say "But not all classes..." or "But some structs..." or whatever - the point is, if it's POD you can zero it, if it's not you can't, but if you think something's POD, zero it, and it turns out NOT to be POD, the world will end. Or at least your program will, nastily. So don't do it.
Apart from anything else, zero is a number like any other. You're just as likely to want to assign/initialise a variable to 1.0f or something. So I'm afraid explicit assignment is the only way to do it.
For something that is POD - like a typical struct - you can do something like this:
struct MyStruct
{
// ... member
}
MyStruct a = { 0 };
Alternatively you could do memset() or ZeroMemory().
However, most classes - and definitely any class that is derived from another class - contain other data than just their members, such as vtable pointers and so forth. I'm sure that someone's going to pick holes and say "But not all classes..." or "But some structs..." or whatever - the point is, if it's POD you can zero it, if it's not you can't, but if you think something's POD, zero it, and it turns out NOT to be POD, the world will end. Or at least your program will, nastily. So don't do it.
Apart from anything else, zero is a number like any other. You're just as likely to want to assign/initialise a variable to 1.0f or something. So I'm afraid explicit assignment is the only way to do it.
What you're asking for can probably be done with a constructor, this won't do it automatically though. Every time you make an instance of the class all the values will be set to 0 however.
class myClass { public: myClass() { pop=pop2=pop3=0; } // inline constructor private: int pop; float pop2; unit * pop3;};myClass class1; // this class's members will automatically have the value 0
Quote:all of them should be set to zero att startup
This is the job of the constructor, to put the class into a stable usable state. If you start to have thirty member variables maybe your design(doesn't sound like you design as you say "when i add new members") needs to be rethought.
If you wanted to reset the class after construction then supply a assignment operator (if a deep copy is required) and create a new class of the type and assign it to the already constructed class.
edit too slow :)
I've had some experience with this too. I had a class in a large project that was constantly getting new members added. When you have 50+ members, it gets really old to set them all to zero. And you have to worry about forgetting to set any new members you add in the umpteen different places that you're setting all the values (if you forget to set the value somewhere, 0 tends to be safer than some random garbage).
What I finally did was memset(&myclassinstance, 0x00, sizeof(myclassinstance));
This isn't correct. It's behavior seems to be compiler dependant (I had success with MSVC6 but devc++ would explode ;)). However, if it doesn't work, it'll be very evident very early on. It won't cause any phantom bugs that I ever discovered.
In short, a memset is a quick and dirty hack that's poor practice if it works at all. But feel free to use it if it works on your platform and you realize that it's poor practice, and comment it as such. No coding police are going to arrest you.
Replace it with a proper constructor when your class starts to stabilize (you stop adding new members), or if you want to distribute a binary (I'm not sure how the exe will behave on other computers from your own.)
What I finally did was memset(&myclassinstance, 0x00, sizeof(myclassinstance));
This isn't correct. It's behavior seems to be compiler dependant (I had success with MSVC6 but devc++ would explode ;)). However, if it doesn't work, it'll be very evident very early on. It won't cause any phantom bugs that I ever discovered.
In short, a memset is a quick and dirty hack that's poor practice if it works at all. But feel free to use it if it works on your platform and you realize that it's poor practice, and comment it as such. No coding police are going to arrest you.
Replace it with a proper constructor when your class starts to stabilize (you stop adding new members), or if you want to distribute a binary (I'm not sure how the exe will behave on other computers from your own.)
Quote:
I've had some experience with this too. I had a class in a large project that was constantly getting new members added. When you have 50+ members, it gets really old to set them all to zero. And you have to worry about forgetting to set any new members you add in the umpteen different places that you're setting all the values (if you forget to set the value somewhere, 0 tends to be safer than some random garbage).
This still smacks of terrible design, and for more than the obvious "too many members" reason -- you've also got the "internal" design of the class flawed because there are "umpteeen" different places to set variables. Fixing the design would still be the optimal solution here.
Quote:
However, if it doesn't work, it'll be very evident very early on. It won't cause any phantom bugs that I ever discovered.
It will cause phantom bugs when you add something to the class that requires specific values to be located in a specific region of memory within the region that is determined by sizeof(classtype) -- the most common example of such is the virtual table pointer, which many implementations will place in the first sizeof(pointer) bytes of an instance.
The argument that you just won't add virtual methods or any such, commonly used to counteract what I just said, doesn't tend to hold water because as you already pointed out, it can be hard to remember something about a class this big.
I am strongly opposed to doing anything that you know to be a bad idea, no matter how much it seems like a good idea (or that you won't forget to fix it later) at the time; doing stupid things intentionally is just that -- stupid.
Besides the poor design, there are more subtle (and admittedly more pedantic) gotchas:
- You cannot reliably store pointers as members of the class (while a constant integral value of zero will be converted to the null pointer value, the value represention of a null pointer is not necessarily zero, and by using memset() you modify the value representation directly).
- You cannot reliably store floating-pointer members (the value representation of floats does not need to be one where 0.0 happens to correspond with an all-zero bitpattern).
- You cannot store any class type that cannot be reliably "zeroed out" via this same ugly technique.
And so on. Just say no to memset, and fix your design.
Quote:Original post by Numsgil
I've had some experience with this too. I had a class in a large project that was constantly getting new members added. When you have 50+ members, it gets really old to set them all to zero. And you have to worry about forgetting to set any new members you add in the umpteen different places that you're setting all the values (if you forget to set the value somewhere, 0 tends to be safer than some random garbage).
What I finally did was memset(&myclassinstance, 0x00, sizeof(myclassinstance));
using a memset on a class is highly dangerous, because if that class has virtual methods, they are cleared too, and that usually causes nasty general protection faults
this is easy:
MyClass my_object;
//......
my_object=MyClass(); //everything reset to 0
you see unless you define a constructor for a class it will create a default constructor which calls the default constructor of all of its members, which is essentially what you want to do. For example if you have a member of type float it will call the constructor for that member setting it to 0.0
MyClass my_object;
//......
my_object=MyClass(); //everything reset to 0
you see unless you define a constructor for a class it will create a default constructor which calls the default constructor of all of its members, which is essentially what you want to do. For example if you have a member of type float it will call the constructor for that member setting it to 0.0
Quote:
this is easy:
MyClass my_object;
//......
my_object=MyClass(); //everything reset to 0
you see unless you define a constructor for a class it will create a default constructor which calls the default constructor of all of its members, which is essentially what you want to do. For example if you have a member of type float it will call the constructor for that member setting it to 0.0
No, it won't. Fundamental types, such as integers and floats, do not have constructors; such types are left uninitialized by an implicit default constructor, and will thus have unpredictable values; what you describe will not work.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement