Topic: Possible defect -- copy constructor's mem-initializer
Author: jdennett@acm.org (James Dennett)
Date: Wed, 16 Oct 2002 23:03:10 +0000 (UTC) Raw View
Alf P. Steinbach wrote:
> This is regarding my earlier posting on copy constructors, why did
> that program compile with both MSVC and g++.
>=20
> Well, I think I found the answer. I only have the CD2, not the final
> standard, but the CD2 says in =A712.6.2/4:
>=20
>=20
> If a given nonstatic data member or base class is not named by a
> meminitializerid in the meminitializerlist, then
>=20
> =97 If the entity is a nonstatic data member of (possibly cvqualified=
)
> class type (or array thereof) or a base class, and the entity class=
is
> a nonPOD class, the entity is defaultinitialized (8.5). If the enti=
ty
> is a nonstatic data member of a constqualified type, the entity cla=
ss
> shall have a userdeclared default constructor.
>=20
> =97 Otherwise, the entity is not initialized. If the entity is of
> constqualified type or reference type, or of a (possibly cvqualifie=
d)
> POD class type (or array thereof) containing (directly or indirectl=
y) a
> member of a constqualified type, the program is illformed. After t=
he
> call to a constructor for class X has completed, if a member of X i=
s neither
> specified in the constructor=92s meminitializers, nor defaultinitia=
lized,
> nor initialized during execution of the body of the constructor, th=
e member
> has indeterminate value.
>=20
>=20
> It seems to me that one *very seldom* wants default initialization of a=
base
> class in a copy constructor. Instead, one wants the base class' copy
> constructor. As it is, forgetting to explicitly name the base class in=
the
> copy constructor's mem-initializer list (very easy if you don't use a m=
em-
> initializer list!) you get code that compiles but likely does "The Wron=
g
> Thing" (TM), namely a default-initialization of the base class.
What about copy constructors which can take other arguments?
struct X
{
X(const X&, bool =3D false);
// ...
};
Should the current, consistent policy of using default constructors
be changed for this constructor? Always? Only when the default is
used?
> Additionally, the current wording (if the final standard didn't fix thi=
s)
> means that a base class cannot specify "no copying" for subclasses with=
out
> also preventing default construction.
Which is fine. There's no need for the base class to stop the derived
class implementing copying if that's not what the base class wants. In
fact, the derived class could specify any constructor when it comes to
copy its base sub-object, so there's no change there.
-- James.
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Thu, 17 Oct 2002 01:41:50 +0000 (UTC) Raw View
On Wed, 16 Oct 2002 23:03:10 +0000 (UTC), jdennett@acm.org (James Dennett) wrote:
>Alf P. Steinbach wrote:
>> This is regarding my earlier posting on copy constructors, why did
>> that program compile with both MSVC and g++.
>>=20
>> Well, I think I found the answer. I only have the CD2, not the final
>> standard, but the CD2 says in =A712.6.2/4:
>>=20
>>=20
>> If a given nonstatic data member or base class is not named by a
>> meminitializerid in the meminitializerlist, then
>>=20
>> =97 If the entity is a nonstatic data member of (possibly cvqualified=
>)
>> class type (or array thereof) or a base class, and the entity class=
> is
>> a nonPOD class, the entity is defaultinitialized (8.5). If the enti=
>ty
>> is a nonstatic data member of a constqualified type, the entity cla=
>ss
>> shall have a userdeclared default constructor.
>>=20
>> =97 Otherwise, the entity is not initialized. If the entity is of
>> constqualified type or reference type, or of a (possibly cvqualifie=
>d)
>> POD class type (or array thereof) containing (directly or indirectl=
>y) a
>> member of a constqualified type, the program is illformed. After t=
>he
>> call to a constructor for class X has completed, if a member of X i=
>s neither
>> specified in the constructor=92s meminitializers, nor defaultinitia=
>lized,
>> nor initialized during execution of the body of the constructor, th=
>e member
>> has indeterminate value.
>>=20
>>=20
>> It seems to me that one *very seldom* wants default initialization of a=
> base
>> class in a copy constructor. Instead, one wants the base class' copy
>> constructor. As it is, forgetting to explicitly name the base class in=
> the
>> copy constructor's mem-initializer list (very easy if you don't use a m=
>em-
>> initializer list!) you get code that compiles but likely does "The Wron=
>g
>> Thing" (TM), namely a default-initialization of the base class.
>
>What about copy constructors which can take other arguments?
>
>struct X
>{
> X(const X&, bool =3D false);
>
> // ...
>};
>
>Should the current, consistent policy of using default constructors
>be changed for this constructor?
I'm not sure what you mean. But assuming you mean the following:
given
class Base
{
std::string myData;
public:
Base( std::string const& someData = "default-constructed" )
: myData( someData )
{}
std::string theData(){ return myData; }
};
struct X: Base
{
X( X const&, bool = false ) {}
};
should the consistent policy of in this case default-constructing Base, i.e.
the current C++ way of by default *not* copying the Base data, be changed?
Yes, that's my opinion.
> Always?
I'm not sure what you mean, but if you mean, always use base copy
constructor as default for copy constructor, yes, absolutely; and
with diagnostic required when base copy constructor isn't available,
just as you would get with an explicit "call" in the initializer list.
> Only when the default is used?
I'm not sure what you mean, but if you mean, the default should not
be forced on the user when an explicit initialization is provided
via the initializer list, then yes of course, anything else would
be senseless (to my mind), and that is the meaning of "default", is
it not???
>> Additionally, the current wording (if the final standard didn't fix thi=
>s)
>> means that a base class cannot specify "no copying" for subclasses with=
>out
>> also preventing default construction.
>
>Which is fine. There's no need for the base class to stop the derived
>class implementing copying if that's not what the base class wants.
I can't make heads or tails of the above statement. Is it "if the
base class doesn't want to stop the derived class from implementing
copying then there is no need for the base class to stop the derived
class from implementing copying"???
The need for specifying that a derived class X does not implement
X( X const& )
pops up in certain contexts where such a derived constructor would
seriously impair efficiency and might break the assumptions of the
base class -- i.e., efficiency + robustness. You'll have to take
my word for it that such cases do exist, and are common (although
most often go unrecognized, with consequences). I'm not at liberty
to disclose the code that prompted my original posting.
>In fact, the derived class could specify any constructor when it comes
>to copy its base sub-object, so there's no change there.
I don't understand that statement at all. Is it that a derived class
copy constructor might choose to explicitly use default construction
of its base class? If so, that's trivially true, but irrelevant; the
problem isn't with explicit use of constructors, but with implicit use.
Cheers,
- Alf
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Wed, 16 Oct 2002 12:06:46 +0000 (UTC) Raw View
This is regarding my earlier posting on copy constructors, why did
that program compile with both MSVC and g++.
Well, I think I found the answer. I only have the CD2, not the final
standard, but the CD2 says in 12.6.2/4:
If a given nonstatic data member or base class is not named by a
meminitializerid in the meminitializerlist, then
If the entity is a nonstatic data member of (possibly cvqualified)
class type (or array thereof) or a base class, and the entity class is
a nonPOD class, the entity is defaultinitialized (8.5). If the entity
is a nonstatic data member of a constqualified type, the entity class
shall have a userdeclared default constructor.
Otherwise, the entity is not initialized. If the entity is of
constqualified type or reference type, or of a (possibly cvqualified)
POD class type (or array thereof) containing (directly or indirectly) a
member of a constqualified type, the program is illformed. After the
call to a constructor for class X has completed, if a member of X is neither
specified in the constructor s meminitializers, nor defaultinitialized,
nor initialized during execution of the body of the constructor, the member
has indeterminate value.
It seems to me that one *very seldom* wants default initialization of a base
class in a copy constructor. Instead, one wants the base class' copy
constructor. As it is, forgetting to explicitly name the base class in the
copy constructor's mem-initializer list (very easy if you don't use a mem-
initializer list!) you get code that compiles but likely does "The Wrong
Thing" (TM), namely a default-initialization of the base class.
Additionally, the current wording (if the final standard didn't fix this)
means that a base class cannot specify "no copying" for subclasses without
also preventing default construction.
Cheers (or grumble grumble)
- Alf
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]