Topic: Default initialization, new, and PODs (was: Syntax question)
Author: Jeff Rife <jrife-news@nabs.net>
Date: 1999/09/04 Raw View
blargg (postmast.root.admi.gov@iname.com) wrote:
> So if we have a non-POD that has no user-supplied default constructor,
> then members will get default initialization?
I would think the program is ill-formed.
In 8.5/5, we have:
"To default initialize an object of type T means:
if T is a non POD class type (clause 9), the default constructor for T
is called (and the initialization is ill formed if T has no accessible
default constructor);"
Does not having a user-supplied default constructor imply that there is
"no accessible default constructor"?
> struct X {
> std::string str;
> void* p;
> };
>
> int main() {
> X* x = new X();
>
> assert( x->p == NULL ); // passes
>
> x = new X;
>
> assert( x->p == NULL ); // undefined
> }
>
> Are the two comments correct (as things were inteneded, that is)?
That's the way I read it, but it could be that this is the actual defect
that Francis was referring to, in that 8.5/5 says "no accessible" and not
"no user-defined".
--
Jeff Rife | "There was a guy that was killed just like this
19445 Saint Johnsbury Lane | over in Jersey."
Germantown, MD 20876-1610 | "Yeah, but I figure, 'What the hell,
Home: 301-916-8131 | that's Jersey.'"
Work: 301-770-5800 Ext 5335 | -- "Highlander"
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/04 Raw View
In article <MPG.123a15db42c6d1479896df@news.nabs.net>, Jeff Rife <jrife-
news@nabs.net> writes
>I would think the program is ill-formed.
>
>In 8.5/5, we have:
>
>"To default initialize an object of type T means:
> if T is a non POD class type (clause 9), the default constructor for T
> is called (and the initialization is ill formed if T has no accessible
> default constructor);"
>
>Does not having a user-supplied default constructor imply that there is
>"no accessible default constructor"?
No because the compiler can generate one.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jeff Rife <jrife-news@nabs.net>
Date: 1999/09/06 Raw View
blargg (postmast.root.admi.gov@iname.com) wrote:
> Guess what happens? Now new Y() doesn't zero-initialize POD and
> builtin members!
>
> Y* y = new Y();
<vocally "ahhhhh">
OK, but is this because there *is* an accessible default constructor,
but it is the compiler-defined one, which doesn't zero-initialize?
The reason I ask, is that without a accessible default constructor,
8.5/5 says the program is ill-formed, and thus should require a
diagnostic. This would still require you to write some new code
yourself, but at least you would *know* if this sort of thing happened.
--
Jeff Rife | "What are you looking at? You're laborers; you
19445 Saint Johnsbury Lane | should be laboring. That's what you get for
Germantown, MD 20876-1610 | not having an education."
Home: 301-916-8131 | -- Professor Hathaway, "Real Genius"
Work: 301-770-5800 Ext 5335 |
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/03 Raw View
In article <user-0209990541340001@aus-as5-141.io.com>, blargg <postmast.
root.admi.gov@iname.com> writes
>So if we have a non-POD that has no user-supplied default constructor,
>then members will get default initialization? For example,
>
> struct X {
> std::string str;
> void* p;
> };
>
> int main() {
> X* x = new X();
>
> assert( x->p == NULL ); // passes
>
> x = new X;
>
> assert( x->p == NULL ); // undefined
> }
>
>Are the two comments correct (as things were inteneded, that is)?
As I understand it, you are correct. The rationale for the change is:
struct X {
char * message;
int * i_ptr;
};
Is a pod and so new X() (and similar usage in template default values)
will result in zero initialisation whereas 'new X' provides initialised
raw memory. Now some people realised that if the programmer provided an
explicit default ctor for the whole then there was no reason to provide
zero initialisation. Unfortunately the rewrite to prevent unwanted zero
initialisation was too all embracing so that if any data member
(recursively) had a user provided default ctor only the default ctor's
would be called - and compiler generate ones do nothing for non static
objects. The result of this is that an implementation decision such as
to change char * to string, or where a class designer adds a default
ctor in the next release of his library can change the behaviour of your
code.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/09/03 Raw View
In article <7LXr+CAVioz3Ew7j@robinton.demon.co.uk>, Francis Glassborow
<francisG@robinton.demon.co.uk> wrote:
> In article <user-0209990541340001@aus-as5-141.io.com>, blargg <postmast.
> root.admi.gov@iname.com> writes
> >So if we have a non-POD that has no user-supplied default constructor,
> >then members will get default initialization? For example,
> >
> > struct X {
> > std::string str;
> > void* p;
> > };
> >
> > int main() {
> > X* x = new X();
> >
> > assert( x->p == NULL ); // passes
> >
> > x = new X;
> >
> > assert( x->p == NULL ); // undefined
> > }
> >
> >Are the two comments correct (as things were inteneded, that is)?
>
> As I understand it, you are correct. The rationale for the change is:
>
> struct X {
> char * message;
> int * i_ptr;
> };
>
> Is a pod and so new X() (and similar usage in template default values)
> will result in zero initialisation whereas 'new X' provides initialised
> raw memory. Now some people realised that if the programmer provided an
> explicit default ctor for the whole then there was no reason to provide
> zero initialisation. Unfortunately the rewrite to prevent unwanted zero
> initialisation was too all embracing so that if any data member
> (recursively) had a user provided default ctor only the default ctor's
> would be called - and compiler generate ones do nothing for non static
> objects. The result of this is that an implementation decision such as
> to change char * to string, or where a class designer adds a default
> ctor in the next release of his library can change the behaviour of your
> code.
<vocally "ahhhhh">
That's nasty. I'll show what Francis is referring to in code, in case
anybody didn't get it completely.
You have some simple POD that uses another POD (and you assume it will
remain that way, since it's just a bunch of data members)
// in library
struct X {
char* message;
// ...
};
// your code
struct Y {
X msg;
int* data;
};
You've read the standard, and know that using new Y() automatically
initializes members to null. This is nice.
Y* y = new Y();
// ...
if ( !y->data )
y->data = new int;
Then, the library innocently uses std::string for the type of message. No
big deal, right? It will make the type safer/clearer to use.
struct X {
std::string message;
// ...
};
Not good. Now X, and any previously-POD users of X, won't be PODs anymore...
struct Y { // not a POD anymore
X msg; // not a POD
int* data;
};
Guess what happens? Now new Y() doesn't zero-initialize POD and builtin members!
Y* y = new Y();
// ...
if ( !y->data ) // undefined - data not initialized
y->data = new int;
Francis is saying that was *meant* to happen (but didn't make it into the
standard) was that data would continue to be zero (default) initialized
*as long as* Y didn't provide a default ctor. If it did, like this, they
wouldn't (but then Y's behavior wouldn't depend on whether X were a POD).
This wouldn't be a source of performance overhead, because the user was
using new Y() all along, explicitly requesting zero initialization.
struct Y {
X msg;
int* data;
Y();
};
With this definition, Y::Y() would have to explicitly initialize data even
with the first definition of X, so there weren't any hidden problems as
there were for the previous definitions of Y under the *current rules in
the standard*.
Definitely, if this behavior was intended, it should be corrected in the
standard. Thanks for mentioning this.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/09/02 Raw View
In article <hW69pNAj7Vz3EwIS@robinton.demon.co.uk>, Francis Glassborow
<francisG@robinton.demon.co.uk> wrote:
> In article <37CD170B.4D449032@physik.tu-muenchen.de>, Christopher
> Eltschka <celtschk@physik.tu-muenchen.de> writes
> >However, in all cases where "new A" is legal, my sytatement
> >above is absolutely correct (unless I've missed something else,
> >that is).
>
> new A does default initialisation. new A() does zero intialisation of
> POD members and was intended to do default initialisation of non-POD
> members (I say was intended because this got lost and is to be corrected
> by a DR)
So if we have a non-POD that has no user-supplied default constructor,
then members will get default initialization? For example,
struct X {
std::string str;
void* p;
};
int main() {
X* x = new X();
assert( x->p == NULL ); // passes
x = new X;
assert( x->p == NULL ); // undefined
}
Are the two comments correct (as things were inteneded, that is)?
I remember reading a comment in D&E that this was even wanted for non-new
cases, i.e.
X x;
assert( x.p == NULL ); // passes
but wasn't accepted due to concerns of efficiency. Put another way, it
would not have been possible to have an unitialized member of a
class/struct when it was on the stack or on the freestore (would this have
even applied to local variables of a built-in type? int i; // i == 0 ? )
Thanks for any clarifications.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]