Because of differences for zero initialization between compilers when using () {} I prefer memset. How safe is this code ?
class A {
public:
int x;
double y[55];
bool a, b;
A() {
memset(&x, 0, int(&b)+sizeof(bool)-int(&x));// cannot use sizeof(A) but I know address of first and last
}
};
I do not have user-defined types, classes, structs from x variable to b variable. I know the address of the first variable and the last. Can I be sure that all the variables defined between x and b, including those in array are zero in all MSVC and Mac compilers after 2010 ?
_____ EDITED _____
Who consider this duplicate, please show me where in the "original" is this solution: memset(&x, 0, int(&b)+sizeof(bool)-int(&x)); ???
This is the key for using memset(), not professional at all to close the thread like this !!!
In meantime I find a more good solution: memset(&x, 0, size_t(&b)+sizeof(bool)-size_t(&x));
There is no difference. It is standardized and hasn't been changed significantly since C++03 in the case of
()
and since C++11 with the addition of{}
. In particular both()
and{}
would have the same effect if your class didn't have a constructor and both would zero-initialize. If your class does have a user-declared/provided constructor, then the class isn't aggregate and so neither()
nor{}
will cause zero-initialization.The memset on the other hand has implementation-defined behavior at best. In particular
int(&b)
is only allowed ifint
is large enough to hold a pointer value (i.e. it will fail on common 64bit systems). If it does work it has an implementation-defined value and everything you do with it is also implementation-defined.Whether
memset
on a pointer tox
instead of theA
object is allowed at all, is another issue of concern.If
A
wasn't trivially-copyable, thenmemset
would have undefined behavior regardless.The correct way to zero-initialize all members of a class explicitly with a non-aggregate class, i.e. one that has a user-declared/provided constructor, is to use the member initializer list to individually value-initialize the members, since C++03 like this:
(With C++11 or later
{}
default member initializers may be used instead as well.)This initializes everything to zero, except padding. If you really need that for some reason and your class is trivially-copyable and
*this
isn't potentially overlapping (i.e. it isn't used as a base class subobject or a member subobject with[[no_unique_address]]
), then a correctmemset
use would be:However, note that
memset
ing all bytes to zero technically also doesn't imply that the members will be set to value zero. It is valid for an implementation to use a different bit pattern than all-zero to represent the zero or null pointer value of a scalar type.