C++ Compiler Generated Member Functions

This page last
updated on:

May 16, 2001

Contents and Related Links

CodeWrangler Pages

Overview

C++ provides a lot of facilities to write safer, more robust code, but it doesn't protect from many kinds of memory problems. One of the most common problems is to forget to define a copy constructor and destructor when resources (typically heap memory) are allocated in the constructor. There are four compiler-generated "give-me's", that can often lead to trouble:

  1. Default constructor, if no constructor's are defined and a default constructor is needed (i.e. an object is default constructed in application code). Note that there may be parameters on a constructor, all of which have default arguments, which results in a default constructor.
  2. Copy constructor, if one is needed in the client / application code, which can be in three situations:
    1. Direct construction of an object by another of the same type
    2. Pass an object into a function by value (creates a copy)
    3. Return an object by value (creates a copy)
  3. Assignment operator, when assigning an object to another of the same type.
  4. Destructor, called whenever an object is destroyed.
An example class with the declarations of the above, to illustrate the member function signatures of each:
  class Employee {
  public:
    Employee (); // default ctor, see note above on default args, which also may be default ctor
    ~Employee(); // dtor
    Employee(const Employee& ); // copy ctor
    Employee& operator=(const Employee& ); // assign op, sometimes called copy assignment operator
  };
There are three forms of direct copy construction syntax (in the client / application code), which result in equivalent results. The first form is highly preferred (for efficiency, safe style, and consistency considerations):
  Employee jack(jill); // Jill is an object of type Employee
  Employee jack = jill; // easily confused with assignment
  Employee jack = Employee(jill); // can be inefficient
An example function declaration, where a copy of the calling argument will be made (copy constructor invoked):
  void promoteEmployee (Employee);
An example function declaration of return by value, where an object copy will be made on return:
  Employee findOldestEmployee();
Safe C++ programming means that any kind of managed resources that have been allocated in the constructor or elsewhere in the class implementation code should have at least one constructor defined (whether it is a default or non-default ctor), a copy constructor, an assignment operator, and a destructor defined. There are many examples of resources that could be allocated:
  • Heap memory (most typical)
  • Shared memory (through operating system specific calls)
  • Semaphores, mutexes, memory locks
  • File opens, closes
  • File or record lock, unlock
Good C++ style (for safe, consistent, readable code) recommends that every class should either implement, disable (by making private), or comment as 'implicit / compiler generated' the following member functions:
  • Default constructor
  • Copy constructor
  • Assignment operator
  • Destructor
If it is appropriate and correct logic for the compiler to generate these member functions (implicitly), then it is usually considered safer and more consistent for the compiler to do it (since people tend to not be as complete or thorough as compilers).

The example Employee class declaration above would have all of the critical member functions implemented. An example of recommended style with the compiler generating all of these methods (this encourages a future maintenance programmer to consider uncommenting if needed) :

  class Employee {
  public:
    // Employee (); // default ctor, implicit
    // ~Employee(); // dtor, implicit
    // Employee(const Employee& ); // copy ctor, implicit
    // Employee& operator=(const Employee& ); // assign op, implicit
  };
An example where copying or assignment of an object will not be allowed (appropriate for many types):
  class Employee {
  private:
    Employee(const Employee& ); // copy ctor, private
    Employee& operator=(const Employee& ); // assign op, private
  };

This page constructed by Cliff Green, Copyright © 2001.