In modern C++, there are six special member functions for a class:
- Default Constructor, a.k.a, ctor,
T() - Copy Constructor, a.k.a, copy ctor,
T(const T&) - Copy Assignment, a.k.a, copy assign,
T& operator=(const T&) - Move Constructor, a.k.a, move ctor,
T(T&&) - Move Assignment, a.k.a, move assign,
T& operator=(T&&) - Destructor, a.k.a, dtor,
~T()
The compiler generated version #
| Special member | Implicitly declared when… | Implicitly deleted when… |
|---|---|---|
| Default ctor | No user-declared constructor | A base/member is not default-constructible |
| Destructor | If not user-declared | A base/member destructor is deleted |
| Copy ctor | No user-declared copy ctor | A base/member is not copy-constructible |
| Copy assign | No user-declared copy assignment | A base/member is not copy-assignable |
| Move ctor | No copy/move ctor/assign and no user-declared destructor | A base/member is not move-constructible |
| Move assign | Same as move ctor | A base/member is not move-assignable |
Deleted means the function is declared (either implicitly or explicitly) but marked unusable. Using it causes a compile-time error.
Copy Constructor vs. Assignment Operator #
| Copy constructor | Assignment operator |
|---|---|
| It is called when a new object is created from an existing object, as a copy of the existing object | This operator is called when an already initialized object is assigned a new value from another existing object. |
| It creates a separate memory block for the new object. | It does not create a separate memory block or new memory space. |
| compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. | A bitwise copy gets created, if the Assignment operator is not overloaded. |
Example
#include <iostream>
#include <stdio.h>
using namespace std;
class Test {
public:
Test() {}
Test(const Test& t)
{
cout << "Copy constructor called " << endl;
}
Test& operator=(const Test& t)
{
cout << "Assignment operator called " << endl;
return *this;
}
};
int main()
{
Test t1, t2;
t2 = t1;
Test t3 = t1;
getchar();
return 0;
}
Output
Assignment operator called
Copy constructor called
The returning type of assigment operator overload #
Although the language accepts other return types, built-in types and all standard library types follow this pattern:
T& T::operator=(const T&);
T& T::operator=(T&&);
Because it enables:
- Chained assignment
a = b = c; // parsed as a.operator=( b.operator=(c) );
For built-in and well-behaved types, this works because each operator= returns a reference to the left-hand side.
- Generic / standard-library concepts
In modern C++20+, the standard defines std::assignable_from<T&, U> in terms of something like:
T& operator=(U);
i.e., the expression t = u must be valid and must yield a T&.
Many STL algorithms and templates expect this behavior — they don’t explicitly say “must return T&” in every doc comment, but they rely on the formal concept definitions that do.
*So:
- Technically
void operator=(...)allowed - But
T&as returning type is effectively the de-facto standard and required for “assignable” semantics in modern C++