______________________________________________________________________

  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.  ]