______________________________________________________________________
12 Special member functions [special]
______________________________________________________________________
1 Some member functions are special in that they affect the way objects
of a class are created, copied, and destroyed, and how values can be
converted to values of other types. Often such special functions are
called implicitly. Also, the compiler can generate instances of these
functions when the programmer does not supply them. Compiler-
generated special functions can be referred to in the same ways that
programmer-written functions are.
2 These member functions obey the usual access rules (_class.access_).
For example, declaring a constructor protected ensures that only
derived classes and friends can create objects using it.
12.1 Constructors [class.ctor]
1 A member function with the same name as its class is called a con
structor; it is used to initialize objects of its class type. 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 or
static.
3 Constructors are not inherited.
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.
_________________________
1) Volatile semantics might or might not be used.
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.2)
+------- BEGIN BOX 1 -------+
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 1 -------+
7 A copy constructor for a class X is a constructor that accepts one
parameter of type X& or of type const X&. See _class.copy_ for more
information on copy constructors.
8 _class.base.init_ describes the order in which constructors for base
classes and non-static members are called and describes how arguments
can be specified for the calls to these constructors.
9 A union member cannot be of a class type (or array thereof) that has a
non-trivial constructor.
10No return type (not even void) can be specified for a constructor. A
return statement in the body of a constructor shall not specify a
return value. It is not possible to take the address of a construc
tor.
11A constructor can be used explicitly to create new objects of its
type, using the syntax
class-name ( expression-listopt )
For example,
complex zz = complex(1,2.3);
cprint( complex(7.8,1.2) );
An object created in this way is unnamed. _class.temporary_ describes
the lifetime of temporary objects.
_________________________
2) When a default constructor for a derived class is implicitly de
fined, all the implicitly-declared default constructors for its bases
and members are also implicitly defined (and this recursively for the
members' base classes and members).
12Some language constructs have special semantics when used during con
struction; 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 com
piler to generate a temporary object. Precisely when such temporaries
are introduced is implementation dependent. For 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 argu
ment. Also, a temporary might be used to hold the result of f(X(2))
before copying it to b using X's copy-constructor; alternatively,
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. Even if the copy
constructor is not called, all the semantic restrictions, such as
accessibility, shall be satisfied.
2 When a compiler 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_). Ordinarily, 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.
3 There are two contexts in which temporaries are destroyed at a differ
ent point then at 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 initializa
tion is complete. The object is initialized from a copy of the tempo
rary; during this copying, an implementation can call the copy con
structor many times; the temporary is destroyed as soon as it has been
copied.
4 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 call. A
temporary bound in a function return statement (_stmt.return_) per
sists until the function exits.
5 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_). For 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 con
version from T to X exists. User-defined conversions are used simi
larly for conversion of initializers (_dcl.init_), function arguments
(_expr.call_, _dcl.fct_), function 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_). As ever access control is
applied after ambiguity resolution (_class.scope_).
4 See _over.match_ for a discussion of the use of conversions in func
tion 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. For 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))
}
2 A nonconverting constructor constructs objects just like converting
constructors, but does so only where a constructor call is explicitly
indicated by the syntax.
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
3 When no converting constructor for class X accepts the given type, no
attempt is made to find other constructors or conversion functions to
convert the assigned value into a type acceptable to a constructor for
class X. For example,
class X {
public:
X(int);
// ...
};
class Y {
public:
Y(X);
// ...
};
Y a = 1; // illegal: Y(X(1)) not tried
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
qualified) same object type (or a reference to it), or to a (possibly
qualified) base class of that type (or a reference to it). If conver
sion-type-id is void or cv-qualified void, the program is ill-formed.
2 Here is an 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(). User-defined conversions are not restricted to use
in assignments and initializations. For example,
void g(X a, X b)
{
int i = (a) ? 1+a : 0;
int j = (a&&b) ? a+b : i;
if (a) { // ...
}
}
3 The conversion-type-id in a conversion-function-id is the longest pos
sible sequence of conversion-declarators. This prevents ambiguities
between the declarator operator * and its expression counterparts. For
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.
4 Conversion operators are inherited.
5 Conversion functions can be virtual.
6 At most one user-defined conversion (constructor or conversion func
tion) is implicitly applied to a single value. For 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()
7 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. For example,
class X {
public:
// ...
operator int();
};
class Y : public X {
public:
// ...
operator void*();
};
void f(Y& a)
{
if (a) { // error: ambiguous
// ...
}
}
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
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.
_________________________
3) Volatile semantics might or might not be used.
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.4)
+------- BEGIN BOX 2 -------+
Should it be specified more precisely at which point in the program
the implicit definition is ill-formed?
+------- END BOX 2 -------+
5 Bases and members are destroyed in reverse of their construction (see
_class.expl.init_). Destructors for elements of an array are called
in reverse order of their construction.
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 Some language constructs have special semantics when used during
destruction; see _class.cdtor_.
8 A union member cannot be of a class type (or array thereof) that
requires 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_). For example,
class X {
// ...
public:
X(int);
~X();
};
_________________________
4) When a destructor for a derived class is implicitly defined, all
the implicitly-declared destructors for its bases and members are also
implicitly defined (and this recursively for the members' base classes
and members).
void g(X*);
void f() // common use:
{
X* p = new X(111); // allocate and initialize
g(p);
delete p; // cleanup and deallocate
}
10Explicit 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
}
11Invocation of destructors is subject to the usual rules for member
functions, e.g., an object of the appropriate type is required (except
invoking delete on a null pointer has no effect). When a destructor
is invoked for an object, the object no longer exists; if the destruc
tor is explicitly invoked again for the same object the behavior is
undefined. For 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.
12The notation for explicit call of a destructor can be used for any
simple type name. For example,
int* p;
// ...
p->int::~int();
Using the notation for a type that does not have a destructor has no
effect. Allowing this enables people to write code without having to
know if a destructor exists for a given type.
13The effect of destroying an object more than once is undefined. This
implies that that explicitly destroying a local variable causes unde
fined behavior on exit from the block, because exiting will attempt to
destroy the variable again. This is true even if the block is exited
because of an exception.
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 a non-array object 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 For 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
}
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.
7 When an object is deleted by a delete-expression, the deallocation
function is looked up in the scope of 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.5)
9 Any deallocation function for a class X is a static member (even if
not explicitly declared static). For example,
_________________________
5) 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.
class X {
// ...
void operator delete(void*);
void operator delete[](void*, size_t);
};
class Y {
// ...
void operator delete(void*, size_t);
void operator delete[](void*);
};
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. For 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.
11Access 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. Thus in
the example above, if B::operator delete() had been private, the
delete expression would have been ill-formed.
12.6 Initialization [class.init]
+------- BEGIN BOX 3 -------+
This needs to be improved to talk about the behavior of all initial
izations; operator new cannot use an initializer-clause; temporary
creation only uses default constructors.
+------- END BOX 3 -------+
1 When no explicit initialization is specified when creating a class
object, if the class has a default constructor (_class.ctor_), the
default constructor is used to initialize the object. If no default
constructor exists for the class and the class has a non-trivial con
structor (_class.ctor_), the object shall be explicitly initialized.
If the class is an aggregate (_dcl.init.aggr_), an initializer-clause
can be used; otherwise, a call to a user-declared constructor shall be
specified.
2 Arrays of objects of class type use constructors in initialization
(_class.ctor_) just as do individual objects. If the array is not
explicitly initialized and the class has a default constructor,
implicit initialization of the array elements occurs by calling the
default constructor for each element of the array, in order of
increasing addresses (_dcl.array_). If no default constructor exists
for the class and the class has a non-trivial constructor, the array
shall be explicitly initialized.
12.6.1 Explicit initialization [class.expl.init]
1 Objects of classes with user-declared constructors (_class.ctor_) can
be initialized with a parenthesized expression list. This list is
taken as the argument list for a call of a constructor doing the ini
tialization. Alternatively for declarations, a single value is speci
fied as the initializer using the = operator. This value is used as
the argument to a copy constructor (_class.ctor_, _class.copy_). Typ
ically, that call of a copy constructor can be eliminated
(_class.temporary_). For 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
Overloading of the assignment operator (_over.ass_) = has no effect on
initialization. See _dcl.init_ for the distinction between the paren
thesized and = forms of initialization.
2 If an array of class objects is initialized with an initializer-clause
(_dcl.init.aggr_), each assignment-expression is treated as an argu
ment in a constructor call to initialize one element of the array,
using the = form of initialization (_dcl.init_). If there are fewer
assignment-expressions in the initializer-clause than elements in the
array, the remaining elements are initialized using the default con
structor for the class. If there is no default constructor and the
initializer-clause is incomplete, the array declaration is ill-formed.
For example,
complex v[6] = { 1,complex(1,2),complex(),2 };
Here, v[0] and v[3] are initialized with complex::complex(double),
v[1] is initialized with complex::complex(double,double), and v[2],
v[4], and v[5] are initialized with complex::complex().
3 The order in which static objects are initialized is described in
_basic.start.init_ and _stmt.dcl_.
12.6.2 Initializing bases and members [class.base.init]
1 The definition of a constructor can specify initializers for direct
and virtual base classes and for nonstatic members not inherited from
a base class. This is most useful for class objects, constants, and
references where the semantics of initialization and assignment dif
fer. A ctor-initializer has the form
ctor-initializer:
: mem-initializer-list
mem-initializer-list:
mem-initializer
mem-initializer , mem-initializer-list
mem-initializer:
::opt nested-name-specifieropt class-name ( expression-listopt )
identifier ( expression-listopt )
The argument list is used to initialize the named nonstatic member or
base class object. This (or for an aggregate (_dcl.init.aggr_), ini
tialization by a brace-enclosed list) is the only way to initialize
nonstatic const and reference members. For 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);
2 If class X has a member m of class type M and M has no default con
structor, then a definition of a constructor for class X is ill-formed
if it does not specify a mem-initializer for m.
3
+------- BEGIN BOX 4 -------+
It needs to be made clear that the order specified below applies for
user-declared constructors as well as for implicitly-declared
constructors.
+------- END BOX 4 -------+
First, the base classes are initialized in declaration order (indepen
dent of the order of mem-initializers), then the members are initial
ized in declaration order (independent of the order of mem-
initializers), then the body of D::D() is executed (_class.ctor_).
The declaration order is used to ensure that sub-objects and members
are destroyed in the reverse order of initialization.
4 Virtual base classes constitute a special case. Virtual bases are
constructed before any nonvirtual bases and in the order they appear
on a depth-first left-to-right traversal of the directed acyclic graph
of base classes; left-to-right is the order of appearance of the base
class names in the declaration of the derived class.
5 The class of a complete object (_intro.object_) is said to be the most
derived class for the sub-objects representing base classes of the
object. All sub-objects for virtual base classes are initialized by
the constructor of the most derived class. If a constructor of the
most derived class does not specify a mem-initializer for a virtual
base class then that virtual base class shall have a default construc
tor. Any mem-initializers for virtual classes specified in a con
structor for a class that is not the class of the complete object are
ignored. For 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()
6 A mem-initializer is evaluated in the scope of the constructor in
which it appears. For example,
class X {
int a;
public:
const int& r;
X(): r(a) {}
};
initializes X::r to refer to X::a for each object of class X.
7 The identifier of a ctor-initializer's mem-initializer in a class'
constructor is looked up in the scope of the class. It shall denote a
nonstatic data member or the type of a direct or virtual base class.
For the purpose of this name lookup, the name, if any, of each class
is considered a nested class member of that class. A constructor's
mem-initializer-list can initialize a base class using any name that
denotes that base class type; the name used can differ from the class
definition. For example:
struct A { A(); };
typedef A global_A;
struct B { };
struct C: public A, public B { C(); };
C::C(): global_A() { } // calls A()
A base class type in a ctor-initializer's mem-initializer shall not
designate both a direct non-virtual base class and an inherited vir
tual base class. For example:
struct A { A(); };
struct B: public virtual A { };
struct C: public A, public B { C(); };
C::C(): A() { } // ill-formed: which A?
8 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-intializer (or in a func
tion called directly or indirectly from a ctor-intializer) before all
the mem-initializers for base classes have completed, the result of
the operation is undefined. For 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
};
9 _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 construc
tion.
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. For 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;
2 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
{ }
};
3 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 and which are also direct or
indirect base classes of X6) 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 non
static member of an object X given a pointer to X, the construction of
X shall have started and the destruction of X shall not have com
pleted, otherwise the computation results in undefined behavior. For
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
{ }
};
4 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
_________________________
6) If X is itself a base class, not all classes derived from B are
necessarily base classes of X.
result of the call is undefined. For 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
}
5 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.
6 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.
7 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
}
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 copy constructor for a class X is a constructor whose first parame
ter is of type X& or const X& and whose other parameters, if any, all
have default arguments (_dcl.fct.default_), so that it can be called
with a single argument of type X. For example, X::X(const X&) and
X::X(X&, int=1) are copy constructors.
+------- BEGIN BOX 5 -------+
Should the parameter of the implicitly-declared copy constructor have
type const volatile X&? See 94-0193R1/N0580R1.
+------- END BOX 5 -------+
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);
3 A constructor for a class X whose first and only parameter is of type
(optionally cv-qualified) X is ill-formed.
4 If there is no user-declared copy constructor, a copy constructor is
implicitly declared 7).
5 If all bases and members of a class X have copy constructors accepting
const parameters, the implicitly-declared copy constructor for X has a
single parameter of type const X&, as follows:
X::X(const X&)
Otherwise it has a single parameter of type X&8):
X::X(X&)
6 An implicitly-declared copy constructor is a public member of its
class. Copy constructors are not inherited.
7 An implicitly-declared copy constructor is implicitly defined when it
is used to copy an object of its class type.
+------- BEGIN BOX 6 -------+
We need to refer to subclauses that describe when class copy takes
place. Is the concept of trivial copy constructor needed?
+------- END BOX 6 -------+
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 copy constructor, or
--a base class with an inaccessible copy constructor. 9)
+------- BEGIN BOX 7 -------+
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 first declaration or expression that does a class copy
causing the implicitly-declared copy constructor to be implicitly-
_________________________
7) Thus the class definition
struct X {
X(const X&, int);
};
causes a copy constructor to be implicitly-declared and the member
function definition
X::X(const X& x, int i =0) { ... }
is ill-formed because of ambiguity.
8) In this case, programs that attempt initialization by copying of
const X objects are ill-formed.
9) When a copy constructor for a derived class is implicitly defined,
all the implicitly-declared copy constructors for the bases and mem
bers are also implicitly defined (and this recursively for the mem
bers' base classes and members).
defined is ill-formed" ?
+------- END BOX 7 -------+
8 The semantics of the implicitly-declared copy constructor are that of
memberwise initialization of the base classes and nonstatic data mem
bers; memberwise initialization implies that if a class X has a member
(or array thereof) or base of a class M, M's copy constructor is used
by X's implicitly-declared copy constructor for the initialization of
the member or base M. Objects representing virtual base classes will
be initialized only once by the implicitly-declared copy constructor.
See _class.expl.init_ for the order of initialization of members and
bases.
9 A copy assignment operator operator= is a non-static member function
of class X with exactly one parameter of type X&or const X&. If there
is no user-declared copy assignment operator, a copy assignment opera
tor is implicitly declared for class X. If all bases and members of a
class X have a copy assignment operators accepting const parameters,
the implicitly-declared copy assignment operator for X will have a
single parameter of type const X&, as follows:
X& X::operator=(const X&)
+------- BEGIN BOX 8 -------+
Should the parameter of the implicitly-declared copy assignment opera
tor have type const volatile X&? See 94-0193R1/N0580R1.
+------- END BOX 8 -------+
Otherwise it will have a single parameter of type X&10):
X& X::operator=(X&)
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 11).
_________________________
10) In this case, programs that attempt assignment by copying of const
X objects will be ill-formed.
11) Given the parameter type for the copy assignment operator, objects
of a derived class type can be assigned to objects of an accessible
base class type. For example,
class X {
public:
int b;
};
class Y : public X {
public:
int c;
};
void f()
{
X x1;
Y y1;
x1 = y1; //1: ok
y1 = x1; // error
10An implicitly-declared copy assignment operator is a public of its
class. Copy assignment operators are not inherited.
11An implicitly-declared copy assignment operator is implicitly defined
when an object of its class type is copied.
+------- BEGIN BOX 9 -------+
We need to refer to subclauses that describe when class copy takes
place. Is the concept of trivial copy assignment operator needed?
+------- END BOX 9 -------+
A program is ill-formed if the class for which a copy assignment oper
ator 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 12)
+------- BEGIN BOX 10 -------+
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 first expression that does a class assignment causing the
implicitly-declared copy assignment operator to be implicitly-defined
is ill-formed" ?
+------- END BOX 10 -------+
12The semantics of the implicitly-declared copy assignment operator are
that of memberwise assignment of the base classes and nonstatic data
members; memberwise assignment implies that if a class X has a member
(or array thereof) or base of a class M, M's copy assignment operator
is used by X's implicitly-declared copy assignment operator for the
assignment of the member or base M. Objects representing virtual base
classes will be assigned only once by a the implicitly-declared copy
assignment operator 13).
_________________________
}
On line //1, y1.b is assigned to x1.b and y1.c is not copied.
12) When a copy assignment operator for a derived class is implicitly
defined, all the implicitly-declared copy assignment operators for the
bases and members are also implicitly defined (and this recursively
for the members' base classes and members).
13) Copying one object into another using the copy constructor or the
copy assignment operator does not change the layout or size of either
object. For example,
struct s {
virtual f();
// ...
+------- BEGIN BOX 11 -------+
This needs more work. See 94-0193R1/N0580R1.
+------- END BOX 11 -------+
_________________________
};
struct ss : public s {
f();
// ...
};
void f()
{
s a;
ss b;
a = b; // really a.s::operator=(b)
b = a; // error
a.f(); // calls s::f
b.f(); // calls ss::f
(s&)b = a; // assign to b's s part
// really ((s&)b).s::operator=(a)
b.f(); // still calls ss::f
}
The call a.f() will invoke s::f() (as is suitable for an object of
class s (_class.virtual_)) and the call b.f() will call ss::f() (as is
suitable for an object of class ss).