· 8 years ago · Feb 20, 2018, 10:06 PM
1/*!
2 * C++ Rule of Five full example
3 * Author: Gary Huang <gh.nctu+code [AT] gmail.com>
4 */
5#ifndef FOO_H
6#define FOO_H
7
8#include <iostream>
9#include <string>
10
11class Foo
12{
13 public:
14 Foo() : m_name(), m_size(0), m_data(nullptr)
15 {
16 std::cout << this << ": construct()" << std::endl;
17 }
18 Foo(std::string name, size_t size)
19 : m_name(std::move(name)),
20 m_size(size),
21 m_data(m_size ? new int[m_size] : nullptr)
22 {
23 std::cout << this << ": construct(name, size)" << std::endl;
24 }
25 Foo(const Foo &other)
26 : m_name(other.m_name),
27 m_size(other.m_size),
28 m_data(m_size ? new int[m_size] : nullptr)
29 // or just
30 // : Foo(name, size)
31 {
32 std::cout << this << ": copy constructor" << std::endl;
33 std::copy(other.m_data, other.m_data + other.m_size, m_data);
34 }
35 Foo(Foo &&other) noexcept
36 : m_name(std::move(other.m_name)),
37 m_size(other.m_size),
38 m_data(other.m_data)
39 {
40 std::cout << this << ": move constructor" << std::endl;
41 other.m_size = 0;
42 other.m_data = nullptr;
43 }
44#if 0
45 // naive
46 Foo &operator=(const Foo &other)
47 {
48 std::cout << this << ": copy assignment" << std::endl;
49 if (this != &other)
50 {
51 size_t n_size = other.m_size;
52 int *n_data = n_size ? new int[n_size] : nullptr;
53 std::copy(other.m_data, other.m_data + other.m_size, n_data);
54
55 delete [] m_data;
56 m_name = other.m_name;
57 m_size = n_size;
58 m_data = n_data;
59 }
60 return *this;
61 }
62 Foo &operator=(Foo &&other) noexcept
63 {
64 std::cout << this << ": move assignment" << std::endl;
65 if (this != &other)
66 {
67 delete [] m_data;
68 m_name = std::move(other.m_name);
69 m_size = other.m_size;
70 m_data = other.m_data;
71 other.m_size = 0;
72 other.m_data = nullptr;
73 }
74 return *this;
75 }
76#else
77 // copy-and-swap idiom
78 // DEPRECATED due to too slow
79 // Foo(Foo &&other)
80 // : m_name(), m_size(0), m_data(nullptr)
81 // // or just
82 // // : Foo()
83 // {
84 // std::cout << this << ": move constructor" << std::endl;
85 // swap(*this, other);
86 // }
87 Foo &operator=(Foo other) noexcept
88 {
89 std::cout << this << ": move/copy assignment" << std::endl;
90 swap(*this, other);
91 return *this;
92 }
93#endif
94 ~Foo()
95 {
96 std::cout << this << ": destruct" << std::endl;
97 delete [] m_data;
98 }
99
100 std::string name() const { return m_name; }
101 size_t size() const { return m_size; }
102
103 friend void swap(Foo &first, Foo &second)
104 {
105 using std::swap;
106 swap(first.m_name, second.m_name);
107 swap(first.m_size, second.m_size);
108 swap(first.m_data, second.m_data);
109 }
110
111 private:
112 std::string m_name;
113 size_t m_size;
114 int *m_data;
115};
116
117#endif // FOO_H