Effective C++ Item 12: Prefer initialization to assignment in constructors

When you write the NamedPtr constructor, you have to transfer the values of the parameters to the corresponding
data members. There are two ways to do this. The first is to use the member initialization list:

template<class T>
NamedPtr<t>::NamedPtr(const string& initName, T *initPtr )
: name(initName), ptr(initPtr)
{}

The second is to make assignments in the constructor body:

template<class T>
NamedPtr<t>::NamedPtr(const string& initName, T *initPtr)
{
    name = initName;
    ptr = initPtr;
}

There are important differences between these two approaches.
From a purely pragmatic point of view, there are times when the initialization list must be used. In particular,
const and reference members may only be initialized, never assigned. So, if you decided that a NamedPtr
object could never change its name or its pointer, you might follow the advice of Item 21 and declare the
members const:

template<class T>
class NamedPtr {
public:
    NamedPtr(const string& initName, T *initPtr);
...
private:
    const string name;
    T * const ptr;
};

This class definition requires that you use a member initialization list, because const members may only be
initialized, never assigned.
You’d obtain very different behavior if you decided that a NamedPtr object should contain a reference to an
existing name. Even so, you’d still have to initialize the reference on your constructors’ member initialization
lists. Of course, you could also combine the two, yielding NamedPtr objects with read-only access to names
that might be modified outside the class:

template<class T>
class NamedPtr {
public:
    NamedPtr(const string& initName, T *initPtr);
...
private:
    const string& name; // must be initialized via
    // initializer list
    T * const ptr; // must be initialized via
    // initializer list
};

The original class template, however, contains no const or reference members. Even so, using a member
initialization list is still preferable to performing assignments inside the constructor. This time the reason is
efficiency. When a member initialization list is used, only a single string member function is called. When
assignment inside the constructor is used, two are called. To understand why, consider what happens when you
declare a NamedPtr object.
Construction of objects proceeds in two phases:
1. Initialization of data members. (See also Item 13.)
2. Execution of the body of the constructor that was called.
(For objects with base classes, base class member initialization and constructor body execution occurs prior to
that for derived classes.)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.