Discussion:
Default intialization without default constructor
(too old to reply)
Alex Blekhman
2010-03-04 15:29:31 UTC
Permalink
Hello,

Recently I noticed that VC++ 2008 compiler can zero initialize a
class instance with the following code:

class X
{
public:
int n1;
int n2;
};

X x1 = X(); // X::n1 and X::n2 are zeroes.

However, if at least one member of the class is not public, then
no initialization occurs whatsoever:

class X
{
public:
int n1;

private:
int n2;
};

X x2 = X(); // X::n1 and X::n2 are garbage.

Now, according to 8.5/7:

"An object whose initializer is an empty set of parentheses,
i.e., (), shall be value-initialized."

So, the expression "X()" should create temporary copy of X, which
is value initialized. According to 8.5/5:

"To value-initialize an object of type T means:
[...]
- if T is a non-union class type without a user-declared
constructor, then every non-static data member and base-class
component of T is value-initialized;
[...]
- otherwise, the object is zero-initialized"

It seem that the expression "X()" should create an instance of X,
which is zero initialized. Then the declared variable of X should
be copy initialized from this temporary instance.

The question is: why it works with all members being public, and
fails if there is at least one non-public member?

Thanks
Alex
Igor Tandetnik
2010-03-04 17:43:31 UTC
Permalink
Post by Alex Blekhman
Recently I noticed that VC++ 2008 compiler can zero initialize a
class X
{
int n1;
int n2;
};
X x1 = X(); // X::n1 and X::n2 are zeroes.
Default initialization for a POD class involves zero-initialization.
Post by Alex Blekhman
However, if at least one member of the class is not public, then
Such a class is not a POD class.
Post by Alex Blekhman
"An object whose initializer is an empty set of parentheses,
i.e., (), shall be value-initialized."
Which version of the standard are you quoting from? My copy of C++98 says "shall be default-initialized" and doesn't mention value-initialization at all. C++0x draft does talk about value initialization, and indeed doesn't make the distinction between POD and non-POD types. I assume VS2008 follows the old rules.

See also

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1999/n1191.pdf
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Igor Tandetnik
2010-03-04 17:58:36 UTC
Permalink
Post by Igor Tandetnik
Post by Alex Blekhman
"An object whose initializer is an empty set of parentheses,
i.e., (), shall be value-initialized."
Which version of the standard are you quoting from? My copy of C++98
says "shall be default-initialized" and doesn't mention
value-initialization at all. C++0x draft does talk about value
initialization, and indeed doesn't make the distinction between POD
and non-POD types. I assume VS2008 follows the old rules.
I now checked C++03, and it includes the "new" rules already. So yes, it's surprising that, five years later, VS2008 still follows the old standard.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Stephan T. Lavavej [MSFT]
2010-03-04 19:50:02 UTC
Permalink
Value-initialization is one of the major differences between C++98 and
C++03.

VC contains nasty bugs when it comes to value-initialization. Basically,
you shouldn't assume that empty parentheses will zero out PODs.
Constructors will always be called, but if you don't see an initializer for
a POD, you should assume that it's garbage. Previously I've seen this
triggered by aggregates of PODs and non-PODs (struct Foo { int x; string
s; }; where the string will be constructed but the int will be garbage), but
it looks like there are other ways to trigger it (mixed access control,
etc.).

(This bug extends to the compiler hooks that power type traits.
Fortunately, in the libraries we're just barely able to work around them, so
is_pod returns the right answer.)

STL
Post by Igor Tandetnik
Post by Alex Blekhman
"An object whose initializer is an empty set of parentheses,
i.e., (), shall be value-initialized."
Which version of the standard are you quoting from? My copy of C++98
says "shall be default-initialized" and doesn't mention
value-initialization at all. C++0x draft does talk about value
initialization, and indeed doesn't make the distinction between POD
and non-POD types. I assume VS2008 follows the old rules.
I now checked C++03, and it includes the "new" rules already. So yes, it's
surprising that, five years later, VS2008 still follows the old standard.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily
a good idea. It is hard to be sure where they are going to land, and it
could be dangerous sitting under them as they fly overhead. -- RFC 1925
Alex Blekhman
2010-03-04 22:18:04 UTC
Permalink
Post by Stephan T. Lavavej [MSFT]
VC contains nasty bugs when it comes to value-initialization.
Well, I hope these nasty bugs are in queue for fixing. It's sad to
see that the most popular C++ compiler on the market fails to get
basic stuff right.
Post by Stephan T. Lavavej [MSFT]
Basically, you shouldn't assume that empty parentheses will zero
out PODs. Constructors will always be called, but if you don't
see an initializer for a POD, you should assume that it's
garbage.
This is my rule of thumb, too. I have never relied on
value-initialization and always provide default c'tor, which
explicitly initializes class members.
Post by Stephan T. Lavavej [MSFT]
Previously I've seen this triggered by aggregates of PODs and
non-PODs (struct Foo { int x; string s; }; where the string will
be constructed but the int will be garbage), but it looks like
there are other ways to trigger it (mixed access control, etc.).
Well, it's quite unfortunate. The Andrew Koenig's defect report
(see the link in Igor's post) contains very good historical
insight and explanation why correct value initialization is
important. I hope to see this feature fixed before I retire from
software engineering.

Thanks
Alex

Loading...