I cannot remember the rules according to which C++ automatically generates some class members, so this note serves as a reminder.
The rules for automatically generating class members for a class T
are:
A copy constructor (which takes a single argument of type const T &
) is generated if all base classes and members are copy-constructible. Note that reference members are copy-constructible.
The parameter-less default constructor is generated if the class does not define any constructor and all base classes and members are default-constructible. This means that once you declare a copy constructor (perhaps to disable the automatically provided one, see below), the compiler will not supply a default construtor.
The copy-assignment operator T &T::operator=(const T &)
is generated if all base classes and members are copy-assignable. For this purpose, reference members are not considered copy-assignable.
The destructor is always automatically supplied if possible, based on the members and the base classes.
In C++11, A move constructor with an argument T &&
is supplied unless the class has any of the following: a user-defined copy constructor, copy-assignment operator, move-assignment operator, or destructor. If the move constructor cannot be implemented because not all bases or members are move-constructible, the supplied move constructor will be defined as deleted.
Similarly, in C++11, a move-assignment operator T &T::operator=(T &&)
is supplied under the same conditions.
Comparison operator such as bool operator==(const T &) const
are never automatically generated by the compiler, even if all base classes and members are comparable.
In order to suppress the automatically generated copy constructor and copy-assignment operator, it is customary in C++03 and earlier to declare them as private
members, but do not define them:
class T { T(const T &); // not implemented T &operator=(const T &); // not implemented public: ... };
This will result in a compile-time error if code which has not private access tries to use this members, or a link-time error for code that has access. In C++11 and later, the delete
should be used because it results in a better diagnostic:
class T { T(const T &) = delete; T &operator=(const T &) = delete; public: ... };
C++11 supports initialization of members as part of the class declaration, like this:
class T { int a = 1; public: explicit T(int); }
Here, the user-defined constructor prevents generation of the default constructor with the initialization operations. Generation of the default constructor can be requested using the default
keyword.
class T { int a = 1; public: explicit T(int); T() = default; }
The rules are fairly simple (as far as things related to C++ are considered), and after writing them down, I will probably never have to look at this note again.
2013-11-02: published