From Java to C++ - copy&move semantics
Tags: cpp, movesemantics, copysemantics, pointer
Published: 2021-11-05 12:46:08

**WARNING!!!WARNING!!!WARNING!!!**
> After consulting with my C++ coach, this article was rewritten almost from scratch. I'm leaving it here for the documentation purposes, but please do not base your learning on it. Visit my blog  for the most recent and valid version - [link](https://www.baremetaldev.com/2021/11/05/from-java-to-c-copymove-semantics/).
WARNING!!!WARNING!!!WARNING!!!

In my opinion, in Java we do not care that much about object creation and then assigning them to other variables. In general, due to GC inner-workings, we're more reluctant in this area, than C++ programmers. However, that's not the only reason why I've decided to write this post. Recently <a href="https://www.incredibuild.com/blog/c-complexity-what-makes-c-complex-for-you">a survey result</a> appeared in my social feed  claiming, that <strong>move semantics</strong> and understanding object lifecycle is not a piece of cake. In order to cover all my bases, I've decided to dive into the topic a little deeper. Here we go. 


**DISCLAIMER!** Obviously I'm not an experienced C++ programmer, therefore there's always a possibility, that my knowledge is not enough. I've put a lot of effort, to write this article and make it as good as possible. However, if you think that some concepts or explanations are wrong, please, don't hesitate to point them out!


<h2>Copy semantics</h2>

I'm mentioning <strong>copy semantics</strong> here, mostly for the sake of completeness, and to introduce some working code example. In fact, it works exactly the same in Java. Every time we assign an already existing object to the new one (or even existing one), a <em>shallow copy</em> is performed. Below code snippet in Java:

```java
class MyObject {
  int i = 5;
  String s = "test";
}


MyObject obj1 = new MyObject();
MyObject obj2 = obj1;

obj1.i = 9;

System.out.println("Obj1: " + obj1.i);
System.out.println("Obj2: " + obj2.i);
```

Will print:

<pre>
Obj1: 9
Obj2: 9
</pre>


For the C++ equivalent we can use this code:

```cpp
#include <iostream>

using namespace std;

class MyObject {
public:
    MyObject()
    {
        i = 5;
        myString[0] = 'a';
    }

    void setMyString(char newString)
    {
        myString[0] = newString;
    }
    char getMyString()
    {
        return myString[0];
    }
private:
    int i;
    char* myString = new char[1];   // size is hardcoded, but we don't care here
};

int main()
{
    MyObject obj1;
    MyObject obj2 = obj1;

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    obj1.setMyString('b');

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    return 0;
}
```

<h3>Passing objects as params - copy it is</h3>

In works in the same way with C++, also when an object is passed to the function/method. As long as we don't operate on <em>references</em> or <em>pointers</em>, a <strong>shallow copy</strong> of the passed object is created, and passed as na argument. Take a look at the following code:

```cpp
#include <iostream>

using namespace std;


class MyObject {
public:
    MyObject()
    {
        i = 5;
        myString[0] = 'a';
    }

    void setMyString(char newString)
    {
        myString[0] = newString;
    }
    char getMyString() const
    {
        return myString[0];
    }
    void setI(int newI)
    {
        i = newI;
    }
    int getI() const
    {
        return i;
    }
private:
    int i;
    char* myString = new char[1];   // size is hardcoded, but we don't care here
};


void doSthWithObject(MyObject myObject)
{
    myObject.setI(9);
}

int main()
{
    MyObject obj1;
    MyObject obj2 = obj1;

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    doSthWithObject(obj1);

    cout << "Obj1: " << obj1.getI() << endl;
    cout << "Obj2: " << obj2.getI() << endl;


    obj1.setMyString('b');

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    return 0;
}
```

Which produces this output:

<pre>
Obj1: a
Obj2: a
Obj1: 5
Obj2: 5
Obj1: b
Obj2: b
</pre>


<h3>Constructor for one?</h3>

So far we saw nothing new. In exactly the same way works a custom constructor (called <em>copy constructor</em>), that takes an object as a parameter. It's up to the programmer how this constructor will create a new object - it can be either simple <em>shallow copy</em>, or even a <em>deep copy</em>:

```cpp
class MyObject {
public:
    MyObject()
    {
        i = 5;
        myString[0] = 'a';
    }

    MyObject(MyObject& obj)
    {
        i = obj.getI();           // shallow copy as it is a primitive/internal object
        myString = new char[1];   // dynamic allocation of memory
        strncpy(myString, new char[1]{obj.getMyString()}, 1);   // copying the VALUE of the object, not the reference
    }

    // set/get methods omitted
private:
    int i;
    char* myString = new char[1];   // size is hardcoded, but we don't care here
};

int main()
{
    MyObject obj1;
    MyObject obj2 = obj1;

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    MyObject obj3 {obj1};    // Usage of COPY CONSTRUCTOR
    cout << "Obj1: " << obj1.getI() << endl;
    cout << "Obj3: " << obj3.getI() << endl;

    obj1.setMyString('b');

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj3: " << obj3.getMyString() << endl;

    return 0;
}
```

Which produces this output:

<pre>
Obj1: a
Obj2: a
Obj1: 5
Obj3: 5
Obj1: b    
Obj3: a   // Value is unaffected
</pre>


<h3>Gimme some equal copy!</h3>

You may say - again - nothing new under the sun. Been there, done that. However, C++ has some more magic to offer than Java. In general, it is possible in C++ to override not only the class methods, but also operators used on it! That's something you can't see in Java (maybe I should add - yet). Overriding an operator is simple - technically it's like overriding a method. However! <strong>With a great power, comes great responsibility!</strong> Let's see how it may go wrong.


```cpp
int main()
{
    MyObject obj1;
    MyObject obj2 = obj1;

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;
    cout << "-----" << endl;

    MyObject obj3;               // New object created
    obj3.setMyString('b');       // New value assigned to the string

    obj3 = obj1;   // Here is the main part!!

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;
    cout << "Obj3: " << obj3.getMyString() << endl;

    return 0;
}
```

The output is as predicted:

<pre>
Obj1: a
Obj2: a
-----
Obj1: a
Obj2: a
Obj3: a
</pre>

The question is - what happens under the hood? In our situation, every new object has its own instance (and therefore dynamically allocated memory) of <strong>myString</strong>. With the default behaviour of the <strong>copy assignment</strong>, we're making only a <em>shallow copy</em> of the string instance when assigning 
<strong>obj1</strong> to <strong>obj3</strong>! The memory allocated for the string instance in the <strong>obj3</strong> leaked! That's something we have to pay attention to, when (re)assigning objects around! In Java, GC process will take care of the lost memory, in C++ - no way. 

So how do we fix this? General rule of thumb is that we need to override the assignment operator, and before we make all the assignments of data, we have to make sure, that we free all the memory we've allocated in the object. The solution in our example should look like this:

```cpp
MyObject& operator=(const MyObject& objToCopyFrom)
{
    if( this == &objToCopyFrom) return *this;         // that prevents unnecessary work if the same instance is passed
    delete[] myString;                                // we free the memory allocated for the array
    myString = new char[1]{objToCopyFrom.getMyString};  // Just use passed object value
    i = objToCopyFrom.getI();            // Same with int - but it's internal type, so no need to think about memory
    return *this;                        // Just return current instance
}
```


<h3>So what's the default behaviour?</h3>

In general, the logic standing behind automatic generation of <a href="https://en.cppreference.com/w/cpp/language/copy_assignment">copy operator</a> and <a href="https://en.cppreference.com/w/cpp/language/copy_constructor">copy constructor</a> is quite robust, and caution is advised while using them. Two objects after copying should not alter their states (as we saw above), and also should not leave any of the objects in the inconsistent state. To finish this topic it is worth mentioning, that there's a possibility to explicitly indicate, that we're fine (or not) with default implementations generated by the compiler. Here are the examples:

```cpp
MyObject(const MyObject&) = default;    // Yes, I'm happy with default implementation
MyObject(const MyObject&) = delete;     // I'm not happy with defaults - remove the auto-generation and raise 
compiler error when such situation occurs
```


<h2>Move semantics</h2>

With the previous chapter we've introduced a foundation for explaining more advanced concept, which is <strong>move semantics</strong>. To start with (and I was surprised to learn that), <strong>move semantics</strong> wasn't present in C++ before <em>C++11</em>! So pay attention to that fact. Second thing that we have to start with, is the difference between <strong>lvalue</strong> and <strong>rvalue</strong>

<h3>Lvalue vs Rvalue</h3>

Here, I would use a direct quote from <em>'C++ Crash Course'</em>:


> We'll consider a very simplified view of value categories. For now, you'll just need a general understanding of 
<strong>lvalues</strong> and <strong>rvalues</strong>. An <strong>lvalue</strong> is any value that has a name, and 
an <strong>rvalue</strong> is anything that isn't an <strong>lvalue</strong>.

To make it easier - here are the usual things that are <strong>rvalues</strong> - temporary objects, literal constants, function return values (unless they're <strong>lvalues</strong> passed as params) and usually results of built-in operators.

I know that it might sound like explaining the unknown through unknown, however, I think that simple code example (taken from the same book) would explain the concept:


```cpp
#include <cstdio>

void ref_type(int &x) {
    printf("lvalue reference %d\n", x);
}

void ref_type(int &&x) {
    printf("rvalue reference %d\n", x);
}

int main() {
    auto x = 1;
    ref_type(x);
    ref_type(2);
    ref_type(x + 2);
}
```

The output is:

<pre>
lvalue reference 1
rvalue reference 2
rvalue reference 3
</pre>


<h3>The idea behind move semantics</h3>

Why this concept is important? Let's go back to the example used in the previous subchapter. Our code there, had an array of chars inside. Imagine for a moment, that this array holds a large amount of chars, like millions or so. Copying all this data back and forth would be a tremendous waste of both - memory and time. What is more, quite often, when we assign an object to the new reference (or we pass it as a constructor parameter), we actually don't care about the source object anymore. We just need new reference to hold the data, and underlying memory does not bother us, as we want to discard the source object. That's the perfect situation when <strong>move semantics</strong> can be used.

Enough talk, show me the code. Let's revisit an example already shown above.

```cpp
#include <iostream>

using namespace std;

class MyObject {
public:
    MyObject()
    {
        i = 5;
        myString[0] = 'a';
    }

    void setMyString(char newString)
    {
        myString[0] = newString;
    }
    char getMyString()
    {
        return myString[0];
    }
private:
    int i;
    char* myString = new char[1];   // size is hardcoded, but we don't care here
};

int main()
{
    MyObject obj1;
    MyObject obj2 = obj1;

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    obj1.setMyString('b');

    cout << "Obj1: " << obj1.getMyString() << endl;
    cout << "Obj2: " << obj2.getMyString() << endl;

    return 0;
}
```

The problem we had before was, that after we've assigned <strong>obj1</strong> to <strong>obj2</strong>, we wanted to use both of them later. Or more precisely, we wanted to use the <strong>objects</strong> that were referenced by <strong>obj1</strong> and <strong>obj2</strong>. As I've mentioned above, quite often we don't need that. We just want to perform a copy of one object (so we're interested in its values), but we don't care that much about the remaining reference. There are two ways to achieve that, similarly to the copying above - through <strong>move constructor</strong> or <strong>move assignment</strong>. What's the difference between them, and their copying counterparts? Just one - usage of <strong>rvalues</strong>. As usual - code speaks thousands words.


```cpp
// I present only the new methods, fields of the class are public for readability
MyObject(MyObject&& obj) noexcept  // Here's the change
{
    i = obj.i;
    myString = new char[1]{*obj.myString};
    // Below we 'empty' the source object.
    obj.i = 0;
    obj.myString = nullptr;
}

MyObject& operator=(MyObject&& objToCopyFrom) noexcept   // Here's the change - RVALUE present as a param
{
    if( this == &objToCopyFrom) return *this;   // that prevents unnecessary work if the same instance is passed
    delete[] myString;                          // we free the memory allocated for the array
    myString = new char[1]{*objToCopyFrom.myString};
    i = objToCopyFrom.i;

    // Below we 'empty' the source object.
    objToCopyFrom.i = 0;
    objToCopyFrom.myString = nullptr;

    return *this;
}
```

We have a couple of changes here that we need to look at. 
<ul>
<li><strong>noexcept</strong> - in general we don't expect these methods to throw any kind of exceptions. We cannibalize the source object, and all the operations are either simple copies of values or reassignment of memory addresses.</li>
<li><strong>no const</strong> - pay attention to that! As we're 'emptying' the source object, we must be able to actually change its state. Therefore we cannot use <strong>const</strong> in the parameters.</li>
<li><strong>emptying source object</strong> - already mentioned this one. In general, we leave the source object 'in statu nascendi', which means it is raw/virgin state. There's no problem with reusing existing reference to assign a new object to it, however the reference itself at this time is 'empty'. </li>
</ul>


The last point above can be a source of the problems. The programmer must always remember to clean up the source object, in order to avoid nasty runtime errors (like double-free ones). Therefore, when possible, try to reuse existing move constructors/operators, or use ```cpp std::exchange``` function, that performs move operation, but also nulls the source object. Here's the code:

```cpp
// This thing
myString = new char[1]{*objToCopyFrom.myString};
objToCopyFrom.myString = nullptr;

// Can be done like this
myString = std::exchange(*objToCopyFrom.myString, nullptr);
```


<h3>Ok, but how I get rvalue?</h3>

That's the valid point. In general, if we create a new object, and at the same time we pass it to the constructor (or assign it) we should be fine. However, the examples above were showing assigning already existing object/reference (so - <strong>lvalue</strong>). To help us with <strong>move semantics</strong> C++ introduced a function in the STD called <strong>move</strong> (its definition can be found in <em><utility></em> header). Its purpose is to cast any <strong>lvalue</strong> to <strong>rvalue</strong>, and therefore to use existing references in the <strong>move semantics</strong>. 

An example from <em>'C++ Crash Course'</em>:

```cpp
#include <cstdio>
#include <utility>

void ref_type(int &x) {
    printf("lvalue reference %d\n", x);
}

void ref_type(int &&x) {
    printf("rvalue reference %d\n", x);
}

int main() {
    auto x = 1;
    ref_type(std::move(x));
    ref_type(2);
    ref_type(x + 2);
}
```

The output is:

<pre>
rvalue reference 1
rvalue reference 2
rvalue reference 3
</pre>


<h3>Summary</h3>

<strong>Copy</strong> and <strong>move</strong> semantics are crucial to understand, in order to properly interact with objects, and understand their lifecycle. Failing to do so, can result in nasty runtime bugs and possible memory leaks. This topic has its own section in the <strong>core guidelines</strong>, that author of the language - Bjarne Stroustrup - created and published for everyone to benefit from. So please, <a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#S-ctor">take a look at them too</a>.


SOURCES:
<ul>
<li><strong>Josh Lospinoso</strong> <em>'C++ Crash Course'</em> book</li>
<li>Back to basics - <a href="https://www.youtube.com/watch?v=ZG59Bqo7qX4&ab_channel=CppCon">Move semantics</a> - CPPCon 2020</li>
<li>Hidden secrets of - <a href="https://www.youtube.com/watch?v=TFMKjL38xAI&ab_channel=CppCon">move semantics</a> - CPPCon 2020</li>
<li>Klaus Iglberger <a href="https://www.youtube.com/watch?v=St0MNEU5b0o&ab_channel=CppCon">Back to Basics: Move Semantics part one</a> and <a href="https://www.youtube.com/watch?v=pIzaZbKUw2s&ab_channel=CppCon">part two</a> from CppCon 2019</li>
</ul>