C++ Move Semantics
Move semantics concepts were first introduced with C++ 11, which is a unique concept that few languages have. Thanks to moving semantics, temporary object creation could be optimized easily without using many tricks to avoid unnecessary copies.
Why do we need move semantic?
- Not to do redundant copying of temporary objects which hurts the performance
- More readable swapping operations
- Not to depend on only pointers.
Before diving into the move semantics, let’s review copy constructing and assignment. Understanding the copy semantics is the first step to grasping move semantics.
When an object is created with another object, the object must be constructed, and the source object’s data is copied to the destination object. This process invokes the copy constructor. In the code example below, firstly “foo” object is created, and the “copy_foo” object is created from the foo object. Defined copy constructor invoked, and attributes of foo object are copied to “copy_foo” object. “foo” object has “bar” attribute, which is a Bar struct instance. Bar struct instance has only one attribute, “val” and Foo class constructor creates an instance of Bar object on the heap. Changing the bar’s value to “10” affects the value of the copy_foo object, as shown in the code snippet below. This is because the copy constructor in the code snippet does a shallow copy, not a deep copy. Only the reference of the Bar object is copied to the new Foo object, not its data. Therefore “foo” and “copy_foo” objects point to the same “bar” object.
The output of the code is given below. As we expected, setting the value of the bar to 10, the copy_foo attribute (bar) value also changed.
The following diagram shows the operation as an abstract concept. Copy constructor of Foo makes an alias to the bar and does not copy the bar object.
Copy assignment is provided by default and copies each object attribute to the destination object. Copy assignment also does a similar operation; however, one big difference between copy constructor and copy assignment is that copy assignment invokes when a constructed object is assigned to another constructed object. The code snippets below show the copy assignment and output.
When the code is executed, it prints “Copy Assignment” since the copied foo object is constructed and then assigned to the foo.
Both objects (“foo”, “copy_foo”) point to the same “bar” object. Therefore, changing the original object’s bar value affects the “copy_foo” object. The copied object holds the same object as it is shown in Figure 1.
Move constructor and move assignment, on the other hand, make a deep copy. So the new object does not share the exact attributes. Each attribute of the object is moved to the new object.
The move constructor is invoked when an object is initialized with an rvalue. The code snippet below shows the move constructor of the “Foo” class. Another object “bar” attribute is moved to a new object “bar” attribute.
Changing the value of “bar” attribute of the “foo” object will not change the “copy_foo” attributes. As seen in the output below, when the value of the bar is changed on foo, the bar attribute of copy_foo is not affected.
Similarly, the move assignment steals the value of the other object. Move assignment is shown in the code snippets below.
When we run the program, the copy_foo object should have “Cat” as the value of its bar attribute. The output of the program is given below.
Note: STL containers will only use the move constructor of an object if that does not throw an exception. Because in case of an exception thrown in the move, the data being processed could be lost, whereas in a copy constructor, the original will not be changed.
Sources and Useful Links
- Shallow vs Deep Copy: https://www.learncpp.com/cpp-tutorial/shallow-vs-deep-copying/
- Copy constructor: https://www.learncpp.com/cpp-tutorial/the-copy-constructor/
- Copy initilization: https://www.learncpp.com/cpp-tutorial/copy-initialization/
- Move constructors and move assignment: https://www.learncpp.com/cpp-tutorial/move-constructors-and-move-assignment/