Summary of Special Member Functions In C++

One example to demonstrate the usage of all C++ special member functions.

This is still a pretty popular topic that you will be given during coding interview.

  1. Default Constructor: ClassName() = default;
  2. Destructor: ~ClassName() = default;
  3. Copy Constructor: ClassName(const ClassName&) = default;
  4. Copy Assignment Operator: ClassName& operator=(const ClassName&) = default;
  5. Move Constructor: ClassName(ClassName&&) = default;
  6. Move Assignment Operator: ClassName& operator=(ClassName&&) = default;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <iostream>

class Shape {
public:
Shape(size_t size = 0)
: size_(size), data_(size ? new int[size] : nullptr) {
std::cout << "Shape constructed with size " << size_ << "\n";
if (data_) {
for (size_t i = 0; i < size_; ++i) {
data_[i] = 0; // Initialize data
}
}
}

virtual ~Shape() {
delete[] data_;
std::cout << "Shape destructed\n";
}

Shape(const Shape& other)
: size_(other.size_), data_(other.size_ ? new int[other.size_] : nullptr) {
if (data_) {
for (size_t i = 0; i < size_; ++i) {
data_[i] = other.data_[i];
}
}
std::cout << "Shape copy-constructed\n";
}

Shape(Shape&& other) noexcept
: size_(other.size_), data_(other.data_) {
other.size_ = 0;
other.data_ = nullptr;
std::cout << "Shape move-constructed\n";
}

Shape& operator=(const Shape& other) {
if (this != &other) {
delete[] data_;
size_ = other.size_;
data_ = other.size_ ? new int[other.size_] : nullptr;
if (data_) {
for (size_t i = 0; i < size_; ++i) {
data_[i] = other.data_[i];
}
}
}
std::cout << "Shape copy-assigned\n";
return *this;
}

Shape& operator=(Shape&& other) noexcept {
if (this != &other) {
delete[] data_;
size_ = other.size_;
data_ = other.data_;
other.size_ = 0;
other.data_ = nullptr;
}
std::cout << "Shape move-assigned\n";
return *this;
}

virtual void describe() const = 0;

protected:
size_t size_;
int* data_;
};

class Rectangle : public Shape {
public:
Rectangle(size_t width = 0, size_t height = 0)
: Shape(width * height), _width(width), _height(height) {
std::cout << "Rectangle constructed with width " << _width
<< " and height " << _height << "\n";
}

Rectangle(const Rectangle& other)
: Shape(other), _width(other._width), _height(other._height) {
std::cout << "Rectangle copy-constructed\n";
}

Rectangle(Rectangle&& other) noexcept
: Shape(std::move(other)), _width(other._width), _height(other._height) {
other._width = 0;
other._height = 0;
std::cout << "Rectangle move-constructed\n";
}

Rectangle& operator=(const Rectangle& other) {
if (this != &other) {
Shape::operator=(other);
_width = other._width;
_height = other._height;
}
std::cout << "Rectangle copy-assigned\n";
return *this;
}

Rectangle& operator=(Rectangle&& other) noexcept {
if (this != &other) {
Shape::operator=(std::move(other));
_width = other._width;
_height = other._height;
other._width = 0;
other._height = 0;
}
std::cout << "Rectangle move-assigned\n";
return *this;
}

~Rectangle() override {
std::cout << "Rectangle destructed\n";
}

void describe() const override {
std::cout << "Rectangle with width " << _width
<< " and height " << _height << "\n";
}

private:
size_t _width;
size_t _height;
};

int main() {
std::cout << "Creating rect1\n";
Rectangle rect1(3, 2); // Outputs: Shape constructed, Rectangle constructed

std::cout << "\nCopy constructing rect2 from rect1\n";
Rectangle rect2(rect1); // Outputs: Shape copy-constructed, Rectangle copy-constructed

std::cout << "\nMove constructing rect3 from rect1\n";
Rectangle rect3(std::move(rect1)); // Outputs: Shape move-constructed, Rectangle move-constructed

std::cout << "\nCopy assigning rect2 to rect3\n";
rect2 = rect3; // Outputs: Shape copy-assigned, Rectangle copy-assigned

std::cout << "\nMove assigning rect3 to rect2\n";
rect3 = std::move(rect2); // Outputs: Shape move-assigned, Rectangle move-assigned

std::cout << "\nDescribing rect3\n";
rect3.describe(); // Outputs: Rectangle with width 3 and height 2

std::cout << "\nEnd of main, destroying objects\n";
// Outputs: Rectangle destructed, Shape destructed for each object

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Creating rect1
Shape constructed with size 6
Rectangle constructed with width 3 and height 2

Copy constructing rect2 from rect1
Shape copy-constructed
Rectangle copy-constructed

Move constructing rect3 from rect1
Shape move-constructed
Rectangle move-constructed

Copy assigning rect2 to rect3
Shape copy-assigned
Rectangle copy-assigned

Move assigning rect3 to rect2
Shape move-assigned
Rectangle move-assigned

Describing rect3
Rectangle with width 3 and height 2

End of main, destroying objects
Rectangle destructed
Shape destructed
Rectangle destructed
Shape destructed
Rectangle destructed
Shape destructed
Author

Joe Chu

Posted on

2024-07-04

Updated on

2024-07-04

Licensed under

Comments