Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++11

C++11 Constructors and Copy Assignment – Part 2

5.00/5 (3 votes)
2 Sep 2014MPL4 min read 12.5K  
C++11 Constructors and Copy Assignment – Part 2

Topics Covered

In this section, we will have a look at more C++ constructors. The following will be covered:

  1. Copy Constructor
  2. Copy Assignment Operators
  3. Move Constructor

Copy Constructor

Definition

General Definition

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments.

Example:

C++
class X {
public:
  X ( const X& );  // Copy Constructor
  X ( const X&, int = 1 );  // Copy Constructor
};

Here the copy constructor is public. This class is call Copy Constructible.

Saying this what happens in the following case?

C++
class X {
public:
  X ( X& x, int i );
  X ( ) { };
};

X::X ( X& x, int i = 0) {

}

We will discuss more of these cases when we dive deeper in another article.

Like normal constructors, these can also be deleted, or default.

C++
X ( const X& ) = default; // Forcing a copy constructor to be generated by the compiler
X ( const X& ) = delete; // Avoiding implicit default constructor

Now the question is; do we always need to pass a reference in copy constructor?

Well let's see the case below:

C++
class X {
public:
  X ( const X v);
};

// Somewhere else in code
X a;
X b = a;

Now what will happen? Here X b = a;  the code will look like b( X v = a). Now this is again a copy constructor call. This will happen like this recursively until we are out of stack space and the program will crash. So this is not allowed. This will throw up error telling this is illegal copy constructor.

A class can have multiple copy constructors, e.g.:

C++
class X {
public:
  X ( const X& );
  X ( X& );
};

A member function template is never instantiated to produce a copy constructor signature. Like:

C++
class X {
public:
 template<typename T>
 X ( T );
 X ( );
};

X a;
void foo ( ) {
 X b ( a ); // does not instantiate the member template to produce X::X<X>(X);
}

In this case, the implicitly declared copy constructor is used.

The reason being follows:

  1. The template can be instantiated to mimic a copy constructor but as per the standard statement it is not a copy constructor (If you haven’t seen the definition see again, it explicitly tells as non-templated). So this means the class doesn’t define one.
  2. The compiler now generates a copy-constructor in the right circumstance. So say the compiler also instantiates this templated code. Then when the time to choose comes, the over loading resolution chooses the non templated function rather than the templated one as it does for other functions.

Implicitly-declared Copy Constructor

If no user-defined copy constructors are provided for a class type, the compiler will always declare a copy constructor with the following type:

C++
class X {
public:
  inline X ( const X& );  // It is public and inline
};

The const modifier is applied only if the following conditions are met:

  • All direct and virtual bases of “X” have copy constructors with references to const or to const volatile as their first parameters.
  • All non-static members of “X” have copy constructors with references to const or to const volatile as their first parameters.
Some Facts
  • The implicitly-defined copy constructor for a non-union class X performs a member-wise copy of its bases and members.
  • The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor.
  • The implicitly-defined copy constructor for a union X copies the object representation of X.

Deleted implicitly-declared copy constructor

The implicitly-declared or defaulted copy constructor for class X is defined as deleted or in simpler pre C++11 terms undefined (the compiler cannot define them) if the following conditions are met:

  • X has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors)
  • X has direct or virtual base class that cannot be copied (has deleted, inaccessible, or ambiguous copy constructors)
  • X has direct or virtual base class with a deleted or inaccessible destructor.

Trivial copy constructor

A trivial copy constructor is a constructor that creates a byte-wise copy of the object representation of the argument and performs no other action. Objects with trivial copy constructors can be copied by copying their object representations manually e.g. with std::memmove. All data types compatible with the C language (POD types) are trivially copyable.

The copy constructor for class X is trivial if all of the following is true:

  • It is not user-provided (that is, it is implicitly-defined or defaulted), and if it is defaulted, its signature is the same as implicitly-defined
  • X has no virtual member functions
  • X has no virtual base classes
  • The copy constructor selected for every direct base of X is trivial
  • The copy constructor selected for every non-static class type (or array of class type) member of X is trivial

Implicitly-defined copy constructor

If the implicitly-declared copy constructor is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler.

  • For union types, the implicitly-defined copy constructor copies the object representation (as by std::memmove).
  • For non-union class types (class and struct), the constructor performs full member-wise copy of the object’s bases and non-static members in their initialization order using direct initialization.

Usage

C++
class X {
public:
  X ( const X& );  // Copy Constructor
};

X a;
// General initialization
X b = a; 
X b ( a );
// Function argument passing
void f ( const X v ); // Function definition
f ( a );
// Return 
void f ( ) {
  X a;
  return a;
}

If a class X only has a copy constructor with a parameter of type X&, an initializer of type const X or volatile X cannot initialize an object of type (possibly cv-qualified) X.

C++
class X {
public:
  X ( ) ; // default constructor
  X ( X& ) ; // copy constructor with a non-const parameter
};
const X a;
X b = a;  // error: X::X(X&) cannot copy a into b

Copy Assignment Operator

Definition

A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&. As with any function and constructor, they can be default or deleted.

C++
class X {
public:
  X& operator=( X );
  X& operator=( const X& );
  X& operator=( const X& ) = default;
  X& operator=( const X& ) = delete;
};

License

This article, along with any associated source code and files, is licensed under The Mozilla Public License 1.1 (MPL 1.1)