______________________________________________________________________
12 Special member functions [special]
______________________________________________________________________
1 [Note: the special member functions affect the way objects of class
type are created, copied, and destroyed, and how values can be con
verted to values of other types. Often such special member functions
are called implicitly. The processor will implicitly declare these
member functions for a class type when the programmer does not explic
itly declare them. ]
+------- BEGIN BOX 1 -------+
"Implicitly-declared special member functions can be referred to in
the same ways that user-declared functions are." Is this true? If
the user does not declare these functions, can these functions be
explicitly called? Can their address be taken?
+------- END BOX 1 -------+
2 These member functions obey the usual access rules (_class.access_).
[Example: declaring a constructor protected ensures that only derived
classes and friends can create objects using it. ]
12.1 Constructors [class.ctor]
1 Constructors do not have names. A special declarator syntax using the
constructor's class name followed by a parameter list is used to
declare the constructor in its class definition. [Example:
class C {
public:
C(); // declares the constructor
};
--end example] A constructor is used to initialize objects of its
class type. Because constructors do not have names, they are never
found during name lookup; however an explicit type conversion using
the functional notation (_expr.type.conv_) will cause a constructor to
be called to initialize an object. [Note: for initialization of
objects of class type see _class.init_. ]
2 A constructor can be invoked for a const, volatile or const volatile
object.1) A constructor shall not be declared const, volatile, or
const volatile (_class.this_). A constructor shall not be virtual
(_class.virtual_) or static (_class.static_).
_________________________
1) Volatile semantics might or might not be used.
3 Constructors are not inherited (_class.derived_).
4 A default constructor for a class X is a constructor of class X that
can be called without an argument. If there is no user-declared con
structor for class X, a default constructor is implicitly declared.
An implicitly-declared default constructor is a public member of its
class. A constructor is trivial if it is an implicitly-declared
default constructor and if:
--its class has no virtual functions (_class.virtual_) and no virtual
base classes (_class.mi_), and
--all the direct base classes of its class have trivial constructors,
and
--for all the nonstatic data members of its class that are of class
type (or array thereof), each such class has a trivial constructor.
5 Otherwise, the constructor is non-trivial.
6 An implicitly-declared default constructor for a class is implicitly
defined when it is used to create an object of its class type
(_basic.stc_). A program is ill-formed if the class for which a
default constructor is implicitly defined has:
--a nonstatic data member of const type, or
--a nonstatic data member of reference type, or
--a nonstatic data member of class type (or array thereof) with an
inaccessible default constructor, or
--a base class with an inaccessible default constructor.
Before the implicitly-declared default constructor for a class is
implicitly defined, all the implicitly-declared default constructors
for its base classes and its nonstatic data members shall have been
implicitly defined.
+------- BEGIN BOX 2 -------+
Should it be specified more precisely at which point in the program
the implicit definition is ill-formed? i.e. is something like this
needed: "The declaration or expression causing the implicit definition
is ill-formed" ?
+------- END BOX 2 -------+
7 [Note: subclause _class.base.init_ describes the order in which con
structors for base classes and non-static data members are called and
describes how arguments can be specified for the calls to these con
structors. ]
8 A copy constructor for a class X is a constructor with a first parame
ter of type X& or of type const X&. [Note: see _class.copy_ for more
information on copy constructors. ]
9 A union member shall not be of a class type (or array thereof) that
has a non-trivial constructor.
10No return type (not even void) shall be specified for a constructor.
A return statement in the body of a constructor shall not specify a
return value. The address of a constructor shall not be taken.
11A constructor can be used explicitly to create new objects of its
type, using the syntax
class-name ( expression-listopt )
[Example:
complex zz = complex(1,2.3);
cprint( complex(7.8,1.2) );
--end example] An object created in this way is unnamed. [Note: sub
clause _class.temporary_ describes the lifetime of temporary objects.
]
12[Note: some language constructs have special semantics when used dur
ing construction; see _class.base.init_ and _class.cdtor_. ]
12.2 Temporary objects [class.temporary]
1 In some circumstances it might be necessary or convenient for the pro
cessor to generate a temporary object. Precisely when such tempo
raries are introduced is implementation-defined. Even when the cre
ation of the temporary object is avoided, all the semantic restric
tions must be respected as if the temporary object was created.
[Example: even if the copy constructor is not called, all the semantic
restrictions, such as accessibility, shall be satisfied. ]
2 [Example:
class X {
// ...
public:
// ...
X(int);
X(const X&);
~X();
};
X f(X);
void g()
{
X a(1);
X b = f(X(2));
a = f(a);
}
Here, an implementation might use a temporary in which to construct
X(2) before passing it to f() using X's copy-constructor; alterna
tively, X(2) might be constructed in the space used to hold the
argument. Also, a temporary might be used to hold the result of
f(X(2)) before copying it to b using X's copy-constructor; alterna
tively, f()'s result might be constructed in b. On the other hand,
the expression a=f(a) requires a temporary for either the argument a
or the result of f(a) to avoid undesired aliasing of a. ]
3 When a processor introduces a temporary object of a class that has a
non-trivial constructor (_class.ctor_), it shall ensure that a con
structor is called for the temporary object. Similarly, the destruc
tor shall be called for a temporary with a non-trivial destructor
(_class.dtor_). Temporary objects are destroyed as the last step in
evaluating the full-expression (_intro.execution_) that (lexically)
contains the point where they were created. This is true even if that
evaluation ends in throwing an exception.
4 There are two contexts in which temporaries are destroyed at a differ
ent point than the end of the full-expression. The first context is
when an expression appears as an initializer for a declarator defining
an object. In that context, the temporary that holds the result of
the expression shall persist until the object's initialization is com
plete. The object is initialized from a copy of the temporary; during
this copying, an implementation can call the copy constructor many
times; the temporary is destroyed as soon as it has been copied.
5 The second context is when a temporary is bound to a reference. The
temporary bound to the reference or the temporary containing the sub-
object that is bound to the reference persists for the lifetime of the
reference initialized or until the end of the scope in which the tem
porary is created, which ever comes first. A temporary holding the
result of an initializer expression for a declarator that declares a
reference persists until the end of the scope in which the reference
declaration occurs. A temporary bound to a reference in a construc
tor's ctor-initializer (_class.base.init_) persists until the con
structor exits. A temporary bound to a reference parameter in a func
tion call (_expr.call_) persists until the completion of the complete
expression containing the call. A temporary bound in a function
return statement (_stmt.return_) persists until the function exits.
6 In all cases, temporaries are destroyed in reverse order of creation.
12.3 Conversions [class.conv]
1 Type conversions of class objects can be specified by constructors and
by conversion functions.
2 Such conversions, often called user-defined conversions, are used
implicitly in addition to standard conversions (_conv_); see
_over.match.user_. [Example: a function expecting an argument of type
X can be called not only with an argument of type X but also with an
argument of type T where a conversion from T to X exists. ] [Note:
user-defined conversions are used similarly for conversion of initial
izers (_dcl.init_), function arguments (_expr.call_, _dcl.fct_), func
tion return values (_stmt.return_, _dcl.fct_), expression operands
(_expr_), expressions controlling iteration and selection statements
(_stmt.select_, _stmt.iter_), and explicit type conversions
(_expr.type.conv_, _expr.cast_). ]
3 User-defined conversions are applied only where they are unambiguous
(_class.member.lookup_, _class.conv.fct_). Conversions obey the
access control rules (_class.access_). Access control is applied
after ambiguity resolution (_class.scope_).
4 [Note: See _over.match_ for a discussion of the use of conversions in
function calls as well as examples below. ]
12.3.1 Conversion by constructor [class.conv.ctor]
1 A constructor declared without the function-specifier explicit that
can be called with a single parameter specifies a conversion from the
type of its first parameter to the type of its class. Such a con
structor is called a converting constructor. [Example:
class X {
// ...
public:
X(int);
X(const char*, int =0);
};
void f(X arg)
{
X a = 1; // a = X(1)
X b = "Jessie"; // b = X("Jessie",0)
a = 2; // a = X(2)
f(3); // f(X(3))
}
--end example]
2 A nonconverting constructor constructs objects just like converting
constructors, but does so only where a constructor call is explicitly
indicated by the syntax. [Example:
class Z {
public:
explicit Z(int);
// ...
};
Z a1 = 1; // error: no implicit conversion
Z a3 = Z(1); // ok: explicit use of constructor
Z a2(1); // ok: explicit use of constructor
Z* p = new Z(1); // ok: explicit use of constructor
--end example]
12.3.2 Conversion functions [class.conv.fct]
1 A member function of a class X with a name of the form
conversion-function-id:
operator conversion-type-id
conversion-type-id:
type-specifier-seq conversion-declaratoropt
conversion-declarator:
ptr-operator conversion-declaratoropt
specifies a conversion from X to the type specified by the conversion-
type-id. Such member functions are called conversion functions.
Classes, enumerations, and typedef-names shall not be declared in the
type-specifier-seq. Neither parameter types nor return type can be
specified. A conversion operator is never used to convert a (possibly
qualified) object (or reference to an object) to the (possibly quali
fied) same object type (or a reference to it), or to a (possibly qual
ified) base class of that type (or a reference to it).2) If conver
sion-type-id is void or cv-qualified void, the program is ill-formed.
2 [Example:
class X {
// ...
public:
operator int();
};
void f(X a)
{
int i = int(a);
i = (int)a;
i = a;
}
In all three cases the value assigned will be converted by
X::operator int(). --end example]
3 User-defined conversions are not restricted to use in assignments and
initializations. [Example:
void g(X a, X b)
{
int i = (a) ? 1+a : 0;
int j = (a&&b) ? a+b : i;
if (a) { // ...
}
}
--end example]
4 The conversion-type-id in a conversion-function-id is the longest pos
sible sequence of conversion-declarators. [Note: this prevents ambi
guities between the declarator operator * and its expression counter
parts. [Example:
&ac.operator int*i; // syntax error:
// parsed as: '&(ac.operator int *) i'
// not as: '&(ac.operator int)*i'
The * is the pointer declarator and not the multiplication operator.
] ]
_________________________
2) Even though never directly called to perform a conversion, such
conversion operators can be declared and can potentially be reached
through a call to a virtual conversion operator in a base class
5 Conversion operators are inherited.
6 Conversion functions can be virtual.
7 At most one user-defined conversion (constructor or conversion func
tion) is implicitly applied to a single value. [Example:
class X {
// ...
public:
operator int();
};
class Y {
// ...
public:
operator X();
};
Y a;
int b = a; // illegal:
// a.operator X().operator int() not tried
int c = X(a); // ok: a.operator X().operator int()
--end example]
8 User-defined conversions are used implicitly only if they are unam
biguous. A conversion function in a derived class does not hide a
conversion function in a base class unless the two functions convert
to the same type. [Example:
class X {
public:
// ...
operator int();
};
class Y : public X {
public:
// ...
operator void*();
};
void f(Y& a)
{
if (a) { // error: ambiguous
// ...
}
}
--end example]
12.4 Destructors [class.dtor]
1 A member function of class cl named ~cl is called a destructor; it is
used to destroy objects of type cl. A destructor takes no parameters,
and no return type can be specified for it (not even void). It is not
possible to take the address of a destructor. A destructor can be
invoked for a const, volatile or const volatile object.3) A destructor
_________________________
3) Volatile semantics might or might not be used.
shall not be declared const, volatile or const volatile
(_class.this_). A destructor shall not be static.
2 If a class has no user-declared destructor, a destructor is declared
implicitly. An implicitly-declared destructor is a public member of
its class. A destructor is trivial if it is an implicitly-declared
destructor and if:
--all of the direct base classes of its class have trivial destructors
and
--for all of the non-static data members of its class that are of
class type (or array thereof), each such class has a trivial
destructor.
3 Otherwise, the destructor is non-trivial.
4 An implicitly-declared destructor is implicitly defined when it is
used to destroy an object of its class type (_basic.stc_). A program
is ill-formed if the class for which a destructor is implicitly
defined has:
--a non-static data member of class type (or array thereof) with an
inaccessible destructor, or
--a base class with an inaccessible destructor.
Before the implicitly-declared destructor for a class is implicitly
defined, all the implicitly-declared destructors for its base classes
and its nonstatic data members shall have been implicitly defined.
+------- BEGIN BOX 3 -------+
Should it be specified more precisely at which point in the program
the implicit definition is ill-formed?
+------- END BOX 3 -------+
5 Bases and members are destroyed in reverse order of their construction
(see _class.base.init_). Destructors for elements of an array are
called in reverse order of their construction (see _class.init_).
6 Destructors are not inherited. A destructor can be declared virtual
(_class.virtual_) or pure virtual (_class.abstract_); if any objects
of that class or any derived class are created in the program, the
destructor shall be defined. If a class has a base class with a vir
tual destructor, its destructor (whether user- or implicitly-
declared) is virtual.
7 [Note: some language constructs have special semantics when used dur
ing destruction; see _class.cdtor_. ]
8 A union member shall not be of a class type (or array thereof) that
has a non-trivial destructor.
9 Destructors are invoked implicitly (1) when an automatic variable
(_basic.stc_) or temporary (_class.temporary_, _dcl.init.ref_) object
goes out of scope, (2) for constructed static (_basic.stc_) objects at
program termination (_basic.start_), and (3) through use of a delete-
expression (_expr.delete_) for objects allocated by a new-expression
(_expr.new_). Destructors can also be invoked explicitly. A delete-
expression invokes the destructor for the referenced object and passes
the address of its memory to a deallocation function (_expr.delete_,
_class.free_). [Example:
class X {
// ...
public:
X(int);
~X();
};
void g(X*);
void f() // common use:
{
X* p = new X(111); // allocate and initialize
g(p);
delete p; // cleanup and deallocate
}
--end example]
10[Note: explicit calls of destructors are rarely needed. One use of
such calls is for objects placed at specific addresses using a new-
expression with the placement option. Such use of explicit placement
and destruction of objects can be necessary to cope with dedicated
hardware resources and for writing memory management facilities. For
example,
void* operator new(size_t, void* p) { return p; }
void f(X* p);
static char buf[sizeof(X)];
void g() // rare, specialized use:
{
X* p = new(buf) X(222); // use buf[]
// and initialize
f(p);
p->X::~X(); // cleanup
}
--end note]
11Invocation of destructors is subject to the usual rules for member
functions (_class.mfct_), e.g., an object of the appropriate type is
required (except invoking delete on a null pointer has no effect).
Once a destructor is invoked for an object, the object no longer
exists; the behavior is undefined if the destructor is invoked for an
object whose lifetime has ended (_basic.life_). [Example: if the
destructor for an automatic object is explicitly invoked, and the
block is subsequently left in a manner that would ordinarily invoke
implicit destruction of the object, the behavior is undefined. --end
example]
12The notation for explicit call of a destructor can be used for any
scalar type name. Using the notation for a type that does not have a
destructor has no effect. [Note: allowing this makes it possible to
write code without having to know if a destructor exists for a given
type. [Example:
int* p;
// ...
p->int::~int();
--end example] --end note]
13
12.5 Free store [class.free]
1 When an object is created with a new-expression (_expr.new_), an allo
cation function (operator new() for non-array objects or
operator new[]() for arrays) is (implicitly) called to get the
required storage (_basic.stc.dynamic.allocation_).
2 When an object of class type T or an array of class T is created by a
new-expression, the allocation function is looked up in the scope of
class T using the usual rules.
3 When a new-expression is executed, the selected allocation function
will be called with the amount of space requested (possibly zero) as
its first argument.
4 Any allocation function for a class X is a static member (even if not
explicitly declared static).
5 [Example:
class Arena; class Array_arena;
struct B {
void* operator new(size_t, Arena*);
};
struct D1 : B {
};
Arena* ap; Array_arena* aap;
void foo(int i)
{
new (ap) D1; // calls B::operator new(size_t, Arena*)
new D1[i]; // calls ::operator new[](size_t)
new D1; // ill-formed: ::operator new(size_t) hidden
}
--end example]
6 When an object is deleted with a delete-expression (_expr.delete_), a
deallocation function (operator delete() for non-array objects or
operator delete[]() for arrays) is (implicitly) called to reclaim the
storage occupied by the object (_basic.stc.dynamic.deallocation_).
7 When an object is deleted by a delete-expression, the deallocation
function is looked up in the scope of the class of the executed
destructor (see _expr.delete_) using the usual rules.
8 When a delete-expression is executed, the selected deallocation func
tion will be called with the address of the block of storage to be
reclaimed as its first argument and (if the two-parameter style is
used) the size of the block as its second argument.4)
9 Any deallocation function for a class X is a static member (even if
not explicitly declared static). [Example:
class X {
// ...
void operator delete(void*);
void operator delete[](void*, size_t);
};
class Y {
// ...
void operator delete(void*, size_t);
void operator delete[](void*);
};
--end example]
10Since member allocation and deallocation functions are static they
cannot be virtual. However, the deallocation function actually called
is determined by the destructor actually called, so if the destructor
is virtual the effect is the same. [Example:
struct B {
virtual ~B();
void operator delete(void*, size_t);
};
struct D : B {
void operator delete(void*);
void operator delete[](void*, size_t);
};
void f(int i)
{
B* bp = new D;
delete bp; // uses D::operator delete(void*)
D* dp = new D[i];
delete [] dp; // uses D::operator delete[](void*, size_t)
}
Here, storage for the non-array object of class D is deallocated by
D::operator delete(), due to the virtual destructor. ]
11For a virtual destructor (whether user- or implicitly- declared), the
deallocation function to be called is determined by looking up the
name of operator delete in the context of the outermost block of that
destructor's definition (ignoring any names defined in that block).
_________________________
4) If the static class in the delete-expression is different from the
dynamic class and the destructor is not virtual the size might be in
correct, but that case is already undefined; see _expr.delete_.
If the result of the lookup is ambiguous or inaccessible, the program
is ill-formed.5)
12Access to the deallocation function is checked statically. Hence,
even though a different one might actually be executed, the statically
visible deallocation function is required to be accessible. [Example:
if B::operator delete() had been private, the delete expression would
have been ill-formed. ]
12.6 Initialization [class.init]
1 If T is either a class type or an array of class type, an object of
type T is default-initialized (_dcl.init_) if:
--the object has static storage duration and no initializer is speci
fied in its declaration (see _dcl.init_), or
--the object is created with a new-expression of the form new T() (see
_expr.new_), or
--the object is a temporary object created using the functional nota
tion for type conversions T() (see _expr.type.conv_), or
--the object is a subobject, either a base of type T or a member m of
type T, of a class object being created by a constructor that speci
fies a mem-initializer of the form T() or m(), respectively (see
_class.base.init_).
2 Furthermore, if an object of class type T (or array thereof)
--has automatic storage duration and no initializer is specified in
its declaration, or
--is created with a new-expression with an omitted new-initializer
(see _expr.new_), or
--is a subobject, either a base of type T or a member m of type T (or
array thereof), of a class object created by a constructor that does
not specify a mem-initializer for T or m, respectively (see
_class.base.init_),
then that object (or, for an array, each element of the array) shall
be initialized by the default constructor for T (and the initializa
tion is ill-formed if T has no accessible default constructor).
_________________________
5) This applies to destructor definitions, not mere declarations. A
similar restriction is not needed for the array version of the delete
operator because _expr.delete_ requires that in all other situations,
the static type of the delete-expression's operand be the same as its
dynamic type.
3 An object of class type (or array thereof) can be explicitly initial
ized; see _class.expl.init_ and _class.base.init_.
4 When an array of class objects is initialized (either explicitly or
implicitly), the constructor shall be called for each element of the
array, following the subscript order; see _dcl.array_. [Note:
destructors for the array elements are called in reverse order of
their construction. ]
12.6.1 Explicit initialization [class.expl.init]
1 An object of class type can be initialized with a parenthesized
expression-list, where the expression-list is construed as an argument
list for a constructor that is called to initialize the object.
Alternatively, a single assignment-expression can be specified as an
initializer using the = form of initialization. Either direct-
initialization semantics or copy-initialization semantics apply; see
_dcl.init_. [Example:
class complex {
// ...
public:
complex();
complex(double);
complex(double,double);
// ...
};
complex sqrt(complex,complex);
complex a(1); // initialize by a call of
// complex(double)
complex b = a; // initialize by a copy of `a'
complex c = complex(1,2); // construct complex(1,2)
// using complex(double,double)
// copy it into `c'
complex d = sqrt(b,c); // call sqrt(complex,complex)
// and copy the result into `d'
complex e; // initialize by a call of
// complex()
complex f = 3; // construct complex(3) using
// complex(double)
// copy it into `f'
complex g = { 1, 2 }; // error; constructor is required
--end example] [Note: overloading of the assignment operator
(_over.ass_) = has no effect on initialization. ]
2 When an aggregate (whether class or array) contains members of class
type and is initialized by a brace-enclosed initializer-list
(_dcl.init.aggr_), each such member is copy-initialized (see
_dcl.init_) by the corresponding assignment-expression. If there are
fewer initializers in the initializer-list than members of the aggre
gate, each member not explicitly initialized shall be copy-initialized
(_dcl.init_) with an initializer of the form T() (_expr.type.conv_),
where T represents the type of the uninitialized member. [Note: sub
clause _dcl.init.aggr_ describes how assignment-expressions in an
initializer-list are paired with the aggregate members they initial
ize. ] [Example:
complex v[6] = { 1,complex(1,2),complex(),2 };
Here, complex::complex(double) is called for the initialization of
v[0] and v[3], complex::complex(double,double) is called for the ini
tialization of v[1], complex::complex() is called for the initializa
tion v[2], v[4], and v[5]. For another example,
class X {
int i;
float f;
complex c;
} x = { 99, 88.8, 77.7 };
Here, x.i is initialized with 99, x.f is initialized with 88.8, and
complex::complex(double) is called for the initialization of x.c. ]
[Note: braces can be elided in the initializer-list for any aggregate,
even if the aggregate has members of a class type with user-defined
type conversions; see _dcl.init.aggr_. ]
3 [Note: if T is a class type with no default constructor, any declara
tion of an object of type T (or array thereof) is ill-formed if no
initializer is explicitly specified (see _class.init_ and _dcl.init_).
]
4 [Note: the order in which objects with static storage duration are
initialized is described in _basic.start.init_ and _stmt.dcl_. ]
12.6.2 Initializing bases and members [class.base.init]
1 In the definition of a constructor for a class, initializers for
direct and virtual base subobjects and nonstatic data members can be
specified by a ctor-initializer, which has the form
ctor-initializer:
: mem-initializer-list
mem-initializer-list:
mem-initializer
mem-initializer , mem-initializer-list
mem-initializer:
mem-initializer-id ( expression-listopt )
mem-initializer-id:
::opt nested-name-specifieropt class-name
identifier
2 Unless the mem-initializer-id names a nonstatic data member of the
constructor's class or a direct or virtual base of that class, the
mem-initializer is ill-formed. A mem-initializer-list can initialize
a base class using any name that denotes that base class type. [Exam
ple:
struct A { A(); };
typedef A global_A;
struct B { };
struct C: public A, public B { C(); };
C::C(): global_A() { } // mem-initializer for base A
--end example] If a mem-initializer-id is ambiguous because it
designates both a direct non-virtual base class and an inherited vir
tual base class, the mem-initializer is ill-formed. [Example:
struct A { A(); };
struct B: public virtual A { };
struct C: public A, public B { C(); };
C::C(): A() { } // ill-formed: which A?
--end example] If a ctor-initializer specifies more than one mem-
initializer for the same member or base, the ctor-initializer is ill-
formed.
3 The expression-list in a mem-initializer is used to initialize the
base class or nonstatic data member subobject denoted by the mem-
initializer-id. The semantics of a mem-initializer are as follows:
--if the expression-list of the mem-initializer is omitted, the base
class or member subobject is default-initialized (see _dcl.init_);
--otherwise, the subobject indicated by mem-initializer-id is direct-
initialized using expression-list as the initializer (see
_dcl.init_).
[Note: if class X has a member m of class type M and M has no default
constructor, then a definition of a constructor for class X is ill-
formed if it does not specify a mem-initializer for m. ] [Note: when
a constructor creates an object of class type X, if X has a nonstatic
data member m that is of const or reference type and if the member is
neither specified in a mem-initializer nor eligible for default-
initialization (_dcl.init_), then m will have an indeterminate value.
[Example:
struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
D(int);
B1 b;
const c;
};
D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4)
{ /* ... */ }
D d(10);
--end example] ]
+------- BEGIN BOX 4 -------+
Should the standard mandate that const members and reference members
be initialized in the ctor-initializer of their owning class?
+------- END BOX 4 -------+
4 Initialization shall proceed in the following order:
--First, and only for the constructor of the most derived class as
described below, virtual base classes shall be initialized in the
order they appear on a depth-first left-to-right traversal of the
directed acyclic graph of base classes, where "left-to-right" is the
order of appearance of the base class names in the derived class
base-specifier-list.
--Then, direct base classes shall be initialized in declaration order
as they appear in the base-specifier-list (regardless of the order
of the mem-initializers).
--Then, nonstatic data members shall be initialized in the order they
were declared in the class definition (again regardless of the order
of the mem-initializers).
--Finally, the body of the constructor is executed.
[Note: the declaration order is mandated to ensure that base and mem
ber subobjects are destroyed in the reverse order of initialization.
]
5 If a complete object (_intro.object_), a nonstatic data member, or an
array element is of class type, its type, for purposes of construc
tion, is considered the most derived class, to distinguish it from the
class type of any base class subobject of the most derived class. All
sub-objects representing virtual base classes are initialized by the
constructor of the most derived class. If the constructor of the most
derived class does not specify a mem-initializer for a virtual base
class V, then V's default constructor is called to initialize the vir
tual base class subobject. If V does not have an accessible default
constructor, the initialization is ill-formed. A mem-initializer nam
ing a virtual base class shall be ignored during execution of the con
structor of any class that is not the most derived class. [Example:
class V {
public:
V();
V(int);
// ...
};
class A : public virtual V {
public:
A();
A(int);
// ...
};
class B : public virtual V {
public:
B();
B(int);
// ...
};
class C : public A, public B, private virtual V {
public:
C();
C(int);
// ...
};
A::A(int i) : V(i) { /* ... */ }
B::B(int i) { /* ... */ }
C::C(int i) { /* ... */ }
V v(1); // use V(int)
A a(2); // use V(int)
B b(3); // use V()
C c(4); // use V()
--end example]
6 Names in the expression-list of a mem-initializer are evaluated in the
scope of the constructor for which the mem-initializer is specified.
[Example:
class X {
int a;
int b;
public:
const int& r;
X(int i): r(a), b(i) {}
};
initializes X::r to refer to X::a and initializes X::b with the value
of the constructor parameter i; this takes place each time an object
of class X is created. ] [Note: this implies that the this pointer
can be used in the expression-list of a mem-initializer to refer to
the object being initialized. ]
7 Member functions (including virtual member functions, _class.virtual_)
can be called for an object under construction. Similarly, an object
under construction can be the operand of the typeid operator
(_expr.typeid_) or of a dynamic_cast (_expr.dynamic.cast_). However,
if these operations are performed in a ctor-initializer (or in a func
tion called directly or indirectly from a ctor-initializer) before all
the mem-initializers for base classes have completed, the result of
the operation is undefined. [Example:
class A {
public:
A(int);
};
class B : public A {
int j;
public:
int f();
B() : A(f()), // undefined: calls member function
// but base A not yet initialized
j(f()) { } // well-defined: bases are all initialized
};
class C {
public:
C(int);
};
class D : public B, C {
int i;
public:
D() : C(f()), // undefined: calls member function
// but base C not yet initialized
i(f()) {} // well-defined: bases are all initialized
};
--end example]
8 [Note: Clause _class.cdtor_ describes the result of virtual function
calls, typeid and dynamic_casts during construction for the well-
defined cases; that is, describes the polymorphic behavior of an
object under construction. ]
12.7 Construction and destruction [class.cdtor]
1 For an object of non-POD class type (_class_), before the constructor
begins execution and after the destructor finishes execution, refer
ring to any nonstatic member or base class of the object results in
undefined behavior. [Example:
struct X { int i; };
struct Y : X { };
struct A { int a; };
struct B : public A { int j; Y y; };
extern B bobj;
B* pb = &bobj; // ok
int* p1 = &bobj.a; // undefined, refers to base class member
int* p2 = &bobj.y.i; // undefined, refers to member's member
A* pa = &bobj; // undefined, upcast to a base class type
B bobj; // definition of bobj
extern X xobj;
int* p3 = &xobj.i; // Ok, X is a POD class
X xobj;
For another example,
struct W { int j; };
struct X : public virtual W { };
struct Y {
int *p;
X x;
Y() : p(&x.j) // undefined, x is not yet constructed
{ }
};
--end example]
2 To explicitly or implicitly convert a pointer to an object of class X
to a pointer to a direct or indirect base class B, the construction of
X and the construction of all of its direct or indirect bases that
directly or indirectly derive from B shall have started and the
destruction of these classes shall not have completed, otherwise the
computation results in undefined behavior. To form a pointer to a
direct nonstatic member of an object X given a pointer to X, the con
struction of X shall have started and the destruction of X shall not
have completed, otherwise the computation results in undefined behav
ior. [Example:
struct A { };
struct B : virtual A { };
struct C : B { };
struct D : virtual A { D(A*); };
struct X { X(A*); };
struct E : C, D, X {
E() : D(this), // undefined: upcast from E* to A*
// might use path E* -> D* -> A*
// but D is not constructed
// D((C*)this), // defined:
// E* -> C* defined because E() has started
// and C* -> A* defined because
// C fully constructed
X(this) // defined: upon construction of X,
// C/B/D/A sublattice is fully constructed
{ }
};
--end example]
3 Member functions, including virtual functions (_class.virtual_), can
be called during construction or destruction (_class.base.init_).
When a virtual function is called directly or indirectly from a con
structor (including from its ctor-initializer) or from a destructor,
the function called is the one defined in the constructor or destruc
tor's own class or in one of its bases, but not a function overriding
it in a class derived from the constructor or destructor's class or
overriding it in one of the other base classes of the complete object
(_intro.object_). If the virtual function call uses an explicit class
member access (_expr.ref_) and the object-expression's type is neither
the constructor or destructor's own class or one of its bases, the
result of the call is undefined. [Example:
class V {
public:
virtual void f();
virtual void g();
};
class A : public virtual V {
public:
virtual void f();
};
class B : public virtual V {
public:
virtual void g();
B(V*, A*);
};
class D : public A, B {
public:
virtual void f();
virtual void g();
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
f(); // calls V::f, not A::f
g(); // calls B::g, not D::g
v->g(); // v is base of B, the call is well-defined, calls B::g
a->f(); // undefined behavior, a's type not a base of B
}
--end example]
4 The typeid operator (_expr.typeid_) can be used during construction or
destruction (_class.base.init_). When typeid is used in a constructor
(including in its ctor-initializer) or in a destructor, or used in a
function called (directly or indirectly) from a constructor or
destructor, if the operand of typeid refers to the object under con
struction or destruction, typeid yields the type_info representing the
constructor or destructor's class. If the operand of typeid refers to
the object under construction or destruction and the static type of
the operand is neither the constructor or destructor's class nor one
of its bases, the result of typeid is undefined.
5 Dynamic_casts (_expr.dynamic.cast_) can be used during construction or
destruction (_class.base.init_). When a dynamic_cast is used in a con
structor (including in its ctor-initializer) or in a destructor, or
used in a function called (directly or indirectly) from a constructor
or destructor, if the operand of the dynamic_cast refers to the object
under construction or destruction, this object is considered to be a
complete object that has the type of the constructor or destructor's
class. If the operand of the dynamic_cast refers to the object under
construction or destruction and the static type of the operand is not
a pointer to or object of the constructor or destructor's own class or
one of its bases, the dynamic_cast results in undefined behavior.
6 [Example:
class V {
public:
virtual void f();
};
class A : public virtual V { };
class B : public virtual V {
public:
B(V*, A*);
};
class D : public A, B {
public:
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
typeid(this); // type_info for B
typeid(*v); // well-defined: *v has type V, a base of B
// yields type_info for B
typeid(*a); // undefined behavior: type A not a base of B
dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B
// results in B*
dynamic_cast<B*>(a); // undefined behavior,
// a has type A*, A not a base of B
}
--end example]
12.8 Copying class objects [class.copy]
1 A class object can be copied in two ways, by initialization
(_class.ctor_, _dcl.init_), including for function argument passing
(_expr.call_) and for function value return (_stmt.return_), and by
assignment (_expr.ass_). Conceptually, these two operations are
implemented by a copy constructor (_class.ctor_) and copy assignment
operator (_over.ass_).
2 A constructor for class X is a copy constructor if its first parameter
is of type X& or const X& and either there are no other parameters or
else all other parameters have default arguments (_dcl.fct.default_).
[Example: X::X(const X&) and X::X(X&, int=1) are copy constructors.
class X {
// ...
public:
X(int);
X(const X&, int = 1);
};
X a(1); // calls X(int);
X b(a, 0); // calls X(const X&, int);
X c = b; // calls X(const X&, int);
--end example] [Note: both forms of copy constructor may be declared
for a class. [Example:
class X {
// ...
public:
X(const X&);
X(X&); // OK
};
--end example] --end note] [Note: if a class X only has a copy con
structor with a parameter of type X&, an initializer of type const X
cannot initialize an object of type (possibily cv-qualified) X.
[Example:
struct X {
X(); // default constructor
X(X&); // copy constructor with a nonconst parameter
};
const X cx;
X x = cx; // error -- X::X(X&) cannot copy cx into x
--end example] --end note]
3 A declaration of a constructor for a class X is ill-formed if its
first parameter is of type (optionally cv-qualified) X and either
there are no other parameters or else all other parameters have
default arguments.
+------- BEGIN BOX 5 -------+
Is a constructor with a parameter of type volatile X& or const
volatile X& a copy constructor? See 95-0056/N0656.
+------- END BOX 5 -------+
4 If the class definition does not explicitly declare a copy construc
tor, one is declared implicitly. Thus, for the class definition
struct X {
X(const X&, int);
};
a copy constructor is implicitly-declared. If the user-declared con
structor is later defined as
X::X(const X& x, int i =0) { ... }
then any use of X's copy constructor is ill-formed because of the
ambiguity; no diagnostic is required.
5 The implicitly-declared copy constructor for a class X will have the
form
X::X(const X&)
if
--each direct or virtual base class B of X has a copy constructor
whose first parameter is of type const B& and
--for all the nonstatic data members of X that are of a class type M
(or array thereof), each such class type has a copy constructor
whose first parameter is of type const M&.6)
Otherwise, the implicitly declared copy constructor will have the form
X::X(X&)
+------- BEGIN BOX 6 -------+
Must an implicitly-declared copy constructor for class X be able to
copy volatile objects of type X? See 95-0056/N0656.
+------- END BOX 6 -------+
An implicitly-declared copy constructor is a public member of its
class. Copy constructors are not inherited.
+------- BEGIN BOX 7 -------+
Question 1: Should the standard require that the implicitly-declared
copy constructor be inline? Question 2: What does "can't be
_________________________
6) This implies that the reference parameter of the implicitly-
declared copy constructor cannot bind to a volatile lvalue; see
_diff.special_.
inherited" mean? If D is derived from B, can you write D::B(const B&)
to refer to B's copy constructor?
+------- END BOX 7 -------+
6 A copy constructor for class X is trivial if it is implicitly declared
and if
--class X has no virtual functions (_class.virtual_) and no virtual
base classes (_class.mi_), and
--each direct base class of X has a trivial copy constructor, and
--for all the nonstatic data members of X that are of class type (or
array thereof), each such class type has a trivial copy constructor;
otherwise the copy constructor is non-trivial.
7 An implicitly-declared copy constructor is implicitly defined if it is
used to copy an object of its class type, even if the implementation
elided its use (_class.temporary_). A program is ill-formed if the
class for which a copy constructor is implicitly defined has:
--a nonstatic data member of class type (or array thereof) with an
inaccessible or ambiguous copy constructor, or
--a base class with an inaccessible or ambiguous copy constructor.
Before the implicitly-declared copy constructor for a class is implic
itly defined, all implicitly-declared copy constructors for its direct
and virtual base classes and its nonstatic data members shall have
been implicitly defined.
+------- BEGIN BOX 8 -------+
Do we want to mandate at which point in a program an implementation
must diagnose that the implicit definition is ill-formed? Or is it
sufficient simply to say the program is ill-formed if the implicit
definition (wherever it happens) violates the stated constraints?
+------- END BOX 8 -------+
8 The implicitly-defined copy constructor for class X performs a member
wise copy of its subobjects. The order of copying is the same as the
order of initialization of bases and members in a user-defined con
structor (see _class.base.init_). Each subobject is copied in the
manner appropriate to its type:
--if the subobject is of class type, the copy constructor for the
class is used;
--if the subobject is an array, each element is copied, in the manner
appropriate to the element type;
--if the subobject is of scalar or pointer-to-member type, the built-
in assignment operator is used.
Virtual base class subobjects shall be copied only once by the implic
itly-defined copy constructor (see _class.base.init_).
9 A user-declared copy assignment operator X::operator= is a non-static
member function of class X with exactly one parameter of type X, X& or
const X&. [Note: more than one form of copy assignment operator may
be declared for a class. ] [Note: if a class X only has a copy
assignment operator with a parameter of type X&, an expression of type
const X cannot be assigned to an object of type X [Example:
struct X {
X()
X& operator=(X&);
};
const X cx;
X x;
x = cx; // error:
// X::operator=(X&) cannot assign cx into x
--end example] --end note]
+------- BEGIN BOX 9 -------+
Is an assignment operator with a parameter of type volatile X& or
const volatile X& a copy assignment operator? See 95-0056/N0656.
+------- END BOX 9 -------+
10If the class definition does not explicitly declare a copy assignment
operator, one is declared implicitly. The implicitly-declared copy
assignment operator for a class X will have the form
X& X::operator=(const X&)
if
--each direct base class B of X has a copy assignment operator whose
parameter is of type const B& and
--for all the nonstatic data members of X that are of a class type M
(or array thereof), each such class type has a copy assignment oper
ator whose parameter is of type const M&.7)
Otherwise, the implicitly declared copy constructor will have the form
X& X::operator=(X&)
+------- BEGIN BOX 10 -------+
Must an implicitly-declared copy assignment operator for class X be
able to assign volatile objects of type X? See 95-0056/N0656.
+------- END BOX 10 -------+
_________________________
7) This implies that the reference parameter of the implicitly-
declared copy assignment operator cannot bind to a volatile lvalue;
see _diff.special_.
The implicitly-declared copy assignment operator for class X has the
return type X&; it returns the object for which the assignment opera
tor is invoked, that is, the object assigned to. An implicitly-
declared copy assignment operator is a public member of its class.
Because a copy assignment operator is implicitly declared for a class
if not declared by the user, a base class copy assignment operator is
always hidden by the copy assignment operator of a derived class
(_over.ass_).
+------- BEGIN BOX 11 -------+
Should the standard require that the implicitly-declared copy assign
ment operator be inline?
+------- END BOX 11 -------+
11A copy assignment operator for class X is trivial if it is implicitly
declared and if
--each direct base class of X has a trivial copy assignment operator,
and
--for all the nonstatic data members of X that are of class type (or
array thereof), each such class type has a trivial copy assignment
operator;
otherwise the copy assignment operator is non-trivial.
12An implicitly-declared copy assignment operator is implicitly defined
when an object of its class type is assigned. A program is ill-formed
if the class for which a copy assignment operator is implicitly
defined has:
--a nonstatic data member of const type, or
--a nonstatic data member of reference type, or
--a nonstatic data member of class type (or array thereof) with an
inaccessible copy assignment operator, or
--a base class with an inaccessible copy assignment operator.
Before the implicitly-declared copy assignment operator for a class is
implicitly defined, all implicitly-declared copy assignment operators
for its direct base classes and its nonstatic data members shall have
been implicitly defined.
+------- BEGIN BOX 12 -------+
Do we want to mandate at which point in a program an implementation
must diagnose that the implicit definition is ill-formed? Or is it
sufficient simply to say the program is ill-formed if the implicit
definition (wherever it happens) violates the stated constraints?
+------- END BOX 12 -------+
13The implicitly-defined copy assignment operator for class X performs
memberwise assignment of its subobjects. The direct base classes of X
are assigned first, in the order of their declaration in the base-
specifier-list, and then the immediate nonstatic data members of X are
assigned, in the order in which they were declared in the class defi
nition. Each subobject is assigned in the manner appropriate to its
type:
--if the subobject is of class type, the copy assignment operator for
the class is used;
--if the subobject is an array, each element is assigned, in the man
ner appropriate to the element type;
--if the subobject is of scalar or pointer-to-member type, the built-
in assignment operator is used.
It is unspecified whether subobjects representing virtual base classes
are assigned more than once by the implicitly-defined copy assignment
operator. [Example:
struct V {
struct A : virtual V { };
struct B : virtual V { };
struct C : B, A { };
it is unspecified whether the virtual base class subobject V is
assigned twice by the implicitly-defined copy assignment operator for
C. --end example]
14[Note: Copying one object into another using the copy constructor or
the copy assignment operator does not change the layout or size of
either object. ]
15Whenever a class object is copied and the implementation can prove
that either the original or the copy will never again be used, an
implementation is permitted to treat the original and the copy as two
different ways of referring to the same object and not perform a copy
at all. In that case, the object is destroyed at the later of times
when the original and the copy would have been destroyed without the
optimization.8)
+------- BEGIN BOX 13 -------+
The terms "can prove that either the original or the copy will never
again be used" need to be better described. Also, Erwin Unruh men
tioned in core-5211 that both the original object and the copy must
have the same type for the optimization to be possible. The type must
be the same both statically and dynamically. (This is to prevent
slicing effects.)
+------- END BOX 13 -------+
_________________________
8) Because only one object is destroyed instead of two, and one copy
constructor is not executed, there is still one object destroyed for
each one constructed.
[Example:
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};
void f(Thing t) { }
void g(Thing t) { t.fun(); }
int main()
{
Thing t1, t2, t3;
f(t1);
g(t2);
g(t3);
t3.fun();
}
Here t1 does not need to be copied when calling f because f does not
use its formal parameter again after copying it. Although g uses its
parameter, the call to g(t2) does not need to copy t2 because t2 is
not used again after it is passed to g. On the other hand, t3 is used
after passing it to g so calling g(t3) is required to copy t3. ]