From: Alex Blekhman on 4 Mar 2010 10:29 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 4 Mar 2010 12:43 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 4 Mar 2010 12:58 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 4 Mar 2010 14:50 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 4 Mar 2010 17:18 "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
|
Pages: 1 Prev: Using pthreads in VS .NET 2003 Next: dot net library from unmanaged C++ |