Created on 2001-07-23.00:00:00 last changed 196 months ago
[Moved to DR at October 2002 meeting.]
Proposed resolution (10/01):
Add the indicated wording to the third-to-last sentence of 6.3 [basic.def.odr] pararaph 2:
A default constructor for a class is used by default initialization or value initialization as specified in 9.4 [dcl.init].
Add a footnote to the indicated bullet in 9.4 [dcl.init] paragraph 5:
Add the indicated wording to the first sentence of 11.4.5 [class.ctor] paragraph 7:
An implicitly-declared default constructor for a class is implicitly defined when it is used (6.3 [basic.def.odr]) to create an object of its class type (6.7.2 [intro.object]).
We've been looking at implementing value-initialization. At one point, some years back, I remember Bjarne saying that something like X() in an expression should produce an X object with the same value one would get if one created a static X object, i.e., the uninitialized members would be zero-initialized because the whole object is initialized at program startup, before the constructor is called.
The formulation for default-initialization that made it into TC1 (in 9.4 [dcl.init]) is written a little differently (see issue 178), but I had always assumed that it would still be a valid implementation to zero the whole object and then call the default constructor for the troublesome "non-POD but no user-written constructor" cases.
That almost works correctly, but I found a problem case:
struct A { A(); ~A(); }; struct B { // B is a non-POD with no user-written constructor. // It has a nontrivial generated constructor. const int i; A a; }; int main () { // Value-initializing a "B" doesn't call the default constructor for // "B"; it value-initializes the members of B. Therefore it shouldn't // cause an error on generation of the default constructor for the // following: new B(); }
If the definition of the B::B() constructor is generated, an error is issued because the const member "i" is not initialized. But the definition of value-initialization doesn't require calling the constructor, and therefore it doesn't require generating it, and therefore the error shouldn't be detected.
So this is a case where zero-initializing and then calling the constructor is not equivalent to value-initializing, because one case generates an error and the other doesn't.
This is sort of unfortunate, because one doesn't want to generate all the required initializations at the point where the "()" initialization occurs. One would like those initializations to be packaged in a function, and the default constructor is pretty much the function one wants.
I see several implementation choices:
Personally, I find option 1 the least objectionable.
History | |||
---|---|---|---|
Date | User | Action | Args |
2008-10-05 00:00:00 | admin | set | status: wp -> cd1 |
2003-04-25 00:00:00 | admin | set | status: dr -> wp |
2002-11-08 00:00:00 | admin | set | messages: + msg774 |
2002-11-08 00:00:00 | admin | set | status: ready -> dr |
2002-05-10 00:00:00 | admin | set | status: review -> ready |
2001-11-09 00:00:00 | admin | set | messages: + msg554 |
2001-11-09 00:00:00 | admin | set | status: open -> review |
2001-07-23 00:00:00 | admin | create |