C++ Library Extensions 2022.12.09
To help learn modern C++ programming
043-ownership.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
5
6/*
7
8 Originally, lvalue reference was introduced to C++ to unburden
9 C++ programmers from the uninitialized pointers.
10
11 For example,
12
13 int* ptr;
14
15 int s = *ptr;
16
17 or
18
19 *ptr = 5;
20
21 is the shortcut to application crash.
22
23 To prevent such misfortune, C++ Standard Committee introduced
24 lvalue reference, which enforces initialization at definition as below;
25
26 int& lvalue_ref = &s;
27
28 Now, let's think about rvalue reference. Rvalue reference was introduced
29 to C++11 Standard for move semantic.
30
31 Rvalue reference is also "a reference." That is, it should also be
32 initialized at the definition.
33
34 int&& rvalue_ref = 5;
35
36 or
37
38 For your convenience,
39
40 int s = 5;
41
42 // it is valid operation.
43 int&& rvalue_reference = std::move(s);
44
45 */
46
48{
49 // The name s names an object on the stack.
50 int s = 5;
51
52 // int&& rvalue_ref = s; // it does not work.
53
54 // std::move is simply type cast to rvalue reference
55 // int&& rvalue_ref = std::move(s);
56
57 // The name rvalue_ref references to the object
58 // named by s.
59 int&& rvalue_ref = (int&&)s;
60
61 // The name lvalue_ref references to the object
62 // named by s
63 int& lvalue_ref = s;
64
65 /*
66 There is no difference between line# 52
67 and line# 54, no difference.
68 */
69
70 stream << "The address of s: " << &s << endl;
71 stream << "The address of rvalue_ref: " << &rvalue_ref << endl;
72 stream << "The address of lvalue_ref: " << &lvalue_ref << endl;
73
74 /*
75 s, rvalue_ref, lvalue_ref are actually the same object.
76
77 lvalue_ref and rvalue_ref are references to s.
78
79 The lifetime of the object named by s
80 is owned by the name s.
81
82 What about lvalue_ref and rvalue_ref ?
83
84 */
85}
86
87
88class ClsType
89{
90 private:
91 bool m_valid{true};
92
93 public:
95 {
96 stream <<"ClsType() called" << endl;
97 }
98
99 ClsType(const ClsType& rhs)
100 {
101 stream << "Copy Constructor called" << endl;
102 }
103
105 {
106 rhs.m_valid = false;
107 stream << "Move Constructor called" << endl;
108 }
109
111 {
112
113 }
114
116 {
117 if(this->m_valid)
118 {
119 stream << "Object cleaned up" << endl;
120 }
121 }
122
123};
124
126{
127 ClsType object;
128
129 stream << "Before entering local block" << endl;
130
131 {
132 // this code does not work.
133 // ClsType&& rvalue_ref = object;
134
135 // this line of code does NOT construct a new instance of type ClsType
136 ClsType && rvalue_ref = std::move(object);
137
138 // this line of code does NOT construct a new instance of type ClsType
139 ClsType & lvalue_ref = rvalue_ref;
140
141 // in this block, both rvalue_ref and lvalue_ref
142 // are simply alias for object
143 //
144 // both rvalue_ref and lvalue_ref
145 // do not own the object.
146 // the object's lifetime is independent
147 // of lvalue_ref and rvalue_ref
148
149 }
150
151 stream << "After leaving local block" << endl;
152
153 // the object defined at line# 122 is
154 // cleaned up after leaving this function block
155}
156
158{
159
160 ClsType object1; // we create an object of type ClsType,
161 // so, the constructor of ClsType() should be called at this point.
162
163 stream << "Before Entering the local block" << endl;
164
165 {
166 // at this point, obj_ref is simply a reference
167 // std::move() is a typecast to ClsType&&
168 // We are not creating an instance of ClsType
169 // so, no copy, no move constructor is called.
170 ClsType && obj_ref = std::move(object1);
171
172 // Now, this is a totally difference story.
173 // we are creating a new instance object2 of type ClsType
174 // object2 is not a reference, and we type cast object1 to ClsType&&
175 // Since we are creating an instance of ClsType,
176 // a constructor of ClsType should be called at this point.
177 // Since we applied std::move(object1)
178 // the ownership of the object named by object1
179 // is moved to object2
180
181 ClsType object2 = std::move(object1); // we are moving the ownership of the object
182 // originally named by object1.
183 // after move, object1 is invalid.
184 // Don't get me wrong.
185 // the destructor of object1 will be still called
186 // what I mean by "invalid" is that
187 // "class invariant" of object1 is INVALID.
188 // its state is destroyed or moved to object2.
189
190 // Now object2 owns the object named by object1,
191 // the ownership moved from object1 to object2.
192 // at the end of this block,
193 // when object2 goes off,
194 // the object originally named by object1,
195 // is moved to object2, then is destroyed at the end of this block.
196 }
197
198 stream << "After leaving the local block" << endl;
199
200}
201
203{
204 ClsType moved_object = std::move(obj);
205}
206
208{
209 ClsType moved_object = std::move(obj);
210}
211
212// this kind of coding fails 9 out of 10 cases.
214{
215
216 ClsType object;
217
218 ClsType& obj_ref = object;
219
221
222 obj_ref.some_operation();
223}
224
225// your program crashes 9 out of 10 cases.
227{
228
229 ClsType object;
230
231 ClsType& obj_ref = object;
232
233 bomb_lurking_in_your_code_rvalue_ref(std::move(object));
234
235 obj_ref.some_operation();
236}
237
238// std::move() is blind. It is a bomb lurking in your code.
239// when you use std::move(), you have to be extra careful.
240
241int main()
242{
243 // test_rvalue_lvalue_reference();
244
245 // understand_the_concept_of_ownership();
246
247 // object_life_time_of_const_and_rvalue_ref();
248
250}
void bomb_lurking_in_your_code(ClsType &obj)
tpf::sstream stream
void object_life_time_of_const_and_rvalue_ref()
void you_should_be_extra_careful_when_using_std_move()
void test_rvalue_lvalue_reference()
void bomb_lurking_in_your_code_rvalue_ref(ClsType &&obj)
auto endl
int main()
void understand_the_concept_of_ownership()
void you_should_be_extra_careful_when_using_ref_move()
void some_operation()
ClsType(ClsType &&rhs)
ClsType(const ClsType &rhs)
constexpr auto endl
Definition: tpf_output.hpp:973
Stream output operators << are implemented.