From: Alex Blekhman on
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

From: Igor Tandetnik on
Alex Blekhman <tkfx.REMOVE(a)yahoo.com> wrote:
> 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.

Default initialization for a POD class involves zero-initialization.

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

Such a class is not a POD class.

> Now, according to 8.5/7:
>
> "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

From: Igor Tandetnik on
Igor Tandetnik <itandetnik(a)mvps.org> wrote:
> Alex Blekhman <tkfx.REMOVE(a)yahoo.com> wrote:
>> Now, according to 8.5/7:
>>
>> "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

From: Stephan T. Lavavej [MSFT] on
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

"Igor Tandetnik" <itandetnik(a)mvps.org> wrote in message
news:eQmKRR8uKHA.5392(a)TK2MSFTNGP05.phx.gbl...
Igor Tandetnik <itandetnik(a)mvps.org> wrote:
> Alex Blekhman <tkfx.REMOVE(a)yahoo.com> wrote:
>> Now, according to 8.5/7:
>>
>> "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

From: Alex Blekhman on
"Stephan T. Lavavej [MSFT]" wrote:
> 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.

> 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.

> 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