2 Wrong Way to Learn Copy Assignment Operator in C++
Tags: cpp, programming, tutorial, computerscience
Published: 2020-04-28 03:44:35

<!-- wp:paragraph -->
<p>While I was introducing myself to C++, I was confused about the syntax of the copy assignment operator in C++ &amp; some of its use-cases. I have learned those lessons the hard way. And so I have decided to write this article, where we see 2 wrong way to learn copy assignment operator in C++ with example. And we also see why we need it &amp; why its syntax like that only. Although I am not an expert or pro but this what I have learned so far from various sources.  </p>
<!-- /wp:paragraph -->


> /!\\\: Originally published @ [www.vishalchovatiya.com](http://www.vishalchovatiya.com/).

<!-- wp:heading -->
<h2>Why Do We Need Copy Assignment Operator in C++?</h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>The simple answer is just to assign data. As we do an assignment in primitive data types like <code>int a; a = 5</code>. Sometimes we also need to do this in our user-defined data type i.e. class/struct. The answer would be the same as copy constructor which I have given <a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="http://www.vishalchovatiya.com/all-about-copy-constructor-in-cpp/" target="_blank"><span style="color:#2d2bb8" class="color">here</span></a>.</li><li>A class could be a complex entity so that we need a special function which does this task. Although compiler provides a default one. But in some cases, you have to define your own copy assignment operation such as:<ol><li>Write your own assignment operator that does the deep copy if you are using dynamic memory.</li><li>Do not allow the assignment of one <a rel="noreferrer noopener" aria-label="object  (opens in a new tab)" href="http://www.vishalchovatiya.com/inside-the-c-object-model/" target="_blank"><span style="color:#1317e2" class="color">object </span></a>to another object or <a rel="noreferrer noopener" aria-label="sub-object (opens in a new tab)" href="http://www.vishalchovatiya.com/memory-layout-of-cpp-object/" target="_blank"><span style="color:#0c2fae" class="color">sub-object</span></a>(object slicing). We can create our own dummy assignment operator and make it <code>private</code> or simply <code>delete</code> it.</li></ol></li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Why Do We Need to Return Something From the Copy Assignment Operator?</h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>While I was learning about the copy assignment operator, I always had a doubt that why do we need to return value from the copy assignment operator function. Let's consider following example:</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":3} -->
<h3>Copy Assignment Operator in C++ With Example</h3>
<!-- /wp:heading -->

```c++
class X
{
public:
    int var;

    X(int x) { this->var = x; }

    X &operator=(const X &rhs)
    {
        this->var = rhs.var;
        return *this;
    }
};

X x1(1), x2(2);
x2 = x1; // Compiler augments into X::x2.operator=(x1);
```

<!-- wp:list -->
<ul><li>Actually, we don't need to, if you look at the above code we are already assigning to a current object i.e. <code>x2</code> using <code>this</code> pointer who called copy assignment operator function. </li><li>I can understand the need for <a href="http://www.vishalchovatiya.com/when-to-use-const-vs-constexpr-in-cpp/"><code><span style="color:#2d24d2" class="color">const</span></code> </a>in the argument of the copy assignment operator function. But the return value was not justifiable to me until I saw the following code:</li></ul>
<!-- /wp:list -->

```c++
X x1(1), x2(2), x3(3);
x3 = x2 = x1;
```

<!-- wp:list -->
<ul><li>If you make return type of copy assignment operator function as <code>void</code>, the compiler won't throw error till you are using <code>x2 = x1;</code>.</li><li>But when assignment chain will be created like <code>x3 = x2 = x1;</code> you have to return something so that it can be an argument on further call to copy assignment operator.</li><li>So we have to return something from the copy assignment operator to support assignment chaining feature. But what should be the appropriate return type? This will lead us to our next point.</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>What Should Be the Appropriate Return Type?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>I know, you will say we have to return a reference to the current object. Yeh! that's correct also but why not <code>return by value</code> or <code>pointer</code>? Ok, then, let's see 2 wrong way to learn copy assignment operator in C++ </p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>No. 1: <strong>Let's try <code>return by value</code></strong></h3>
<!-- /wp:heading -->

```c++
class X
{
public:
    int var;

    X(int x) { this->var = x; }

    X operator=(X &rhs)
    {
        this->var = rhs.var;
        return *this;
    }
};

int main()
{
    X x1(1), x2(2), x3(3);

    x2 = x1;        // Statement 1: Works fine
    (x3 = x2) = x1; // Statement 2: Correct, but meaning less statement
    x3 = (x2 = x1); // Statement 3: Meaningful but compiler won't alllow us
    x3 = x2 = x1;   // Statement 4: Meaningful but compiler won't alllow us

    cout << x1.var << endl;
    cout << x2.var << endl;
    cout << x3.var << endl;

    return 0;
}
```

<!-- wp:paragraph -->
<p>Note that I have not taken an argument as <a rel="noreferrer noopener" aria-label="const (opens in a new tab)" href="http://www.vishalchovatiya.com/when-to-use-const-vs-constexpr-in-cpp/" target="_blank"><span style="color:#0e03e2" class="color">const</span></a> in copy assignment operator.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>When you will compile the above code, GCC will throw an error as follows:</li></ul>
<!-- /wp:list -->

```c++
error: no viable overloaded '='
  x3 = (x2 = x1);   // Statement 3: Meaningful but compiler won't alllow us
  ~~ ^ ~~~~~~~~~
note: candidate function not viable: expects an l-value for 1st argument
  X operator = (X &rhs){
    ^
```

<!-- wp:list -->
<ul><li>Let's understand all these statements one-by-one</li></ul>
<!-- /wp:list -->

```c++
x2 = x1;          // Statement 1: Works fine</pre>
```

<!-- wp:list -->
<ul><li>Above statement is correct &amp; works fine as we are not utilising return value provided by the copy assignment operator.</li></ul>
<!-- /wp:list -->

```c++
(x3 = x2) = x1;   // Statement 2: Correct, but meaningless statement</pre>
```

<!-- wp:list -->
<ul><li>This statements is perfectly fine &amp; have no problem in a compilation. But <code>Statement 2</code> is meaningless as we are first assigning <code>x2</code> into <code>x3</code> which returns a temporary(AKA anonymous) object which again calls a copy assignment operator with <code>x1</code> as an argument. This works fine but at the end call of the copy assignment operator, we are assigning the value of <code>x1</code> to a temporary object which is meaningless.</li><li>Probable transformation of <code>Statement 2</code> by the compiler would be</li></ul>
<!-- /wp:list -->

```c++
(X::x3.operator=(x2)).operator=(x1);
```

<!-- wp:list -->
<ul><li>With more simplicity</li></ul>
<!-- /wp:list -->

```c++
X temp = X::x3.operator=(x2);
X::temp.operator=(x1);
```

<!-- wp:list -->
<ul><li>As you can see I have taken <code>temp</code> object which usually created by the compiler as we are returning an object by value. So this way output would be <code>1 2 2</code> which is not correct. </li><li>Now we will observe <code>Statement 3</code></li></ul>
<!-- /wp:list -->

```c++
x3 = (x2 = x1);   // Statement 3: Meaningful but compiler won't allow us
```

<!-- wp:list -->
<ul><li>Probable transformation of <code>Statement 3</code> by the compiler would be</li></ul>
<!-- /wp:list -->

```c++
(X::x3.operator=((x2 = x1));
```

<!-- wp:list -->
<ul><li>Code till operation <code>x2 = x1</code> is fine we have seen it earlier but when the result of that operation becomes an argument to another copy assignment operator function, it will again create the problem of temporary object binding to a non-const reference. </li><li>If you don't know about "<a rel="noreferrer noopener" aria-label="temporary object binding to non-const reference (opens in a new tab)" href="http://www.vishalchovatiya.com/lvalue-rvalue-and-their-references-with-example-in-cpp/" target="_blank"><span style="color:#0f0ce5" class="color">temporary object binding to non-const reference</span></a>" then you should find out the reason behind why the following program is not working, you will understand everything you wanted to know for <code>Statement 3</code>.</li></ul>
<!-- /wp:list -->

```c++
int main()
{
    const string &amp;val1 = string("123"); // Works fine
    string &amp;val2 = string("123");       // Will throw error
    return 0;
}
```

<!-- wp:list -->
<ul><li>Error:</li></ul>
<!-- /wp:list -->

```c++
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
exit status 1
error: non-const lvalue reference to type 'basic_string<...>' cannot bind to a temporary of type 'basic_string<...>'
  string& val2 = string("123");
          ^      ~~~~~~~~~~~~~
1 error generated.
```

<!-- wp:list -->
<ul><li>Note that the above code will work in some of the old compilers like VC2012, etc. Now we will move to <code>Statement 4</code></li></ul>
<!-- /wp:list -->

```c++
x3 = x2 = x1;     // Statement 4: Meaningful but compiler won't allow us
```

<!-- wp:list -->
<ul><li>This will also throw the same error as <code>Statement 3</code> because conceptually both are same. Although <code>Statement 3</code> &amp; <code>Statement 4</code> can also be valid if you modify argument of copy assignment operator from <code>pass by reference</code> to <code>pass by value</code> which we know adds the unnecessary overhead of calling copy constructor which also stands true for the return type.</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":3} -->
<h3>  No.  2: <strong>Let's try <code>return by pointer</code></strong> </h3>
<!-- /wp:heading -->

```c++
class X
{
public:
    int var;

    X(int x) { this->var = x; }

    X *operator=(X &rhs)
    {
        this->var = rhs.var;
        return this;
    }
};

int main()
{
    X x1(1), x2(2), x3(3);

    x2 = x1;      // Statement 1: Works fine
    x3 = x2 = x1; // Statement 4: Meaningful but compiler won't alllow us

    cout << x1.var << endl;
    cout << x2.var << endl;
    cout << x3.var << endl;

    return 0;
}
```

<!-- wp:list -->
<ul><li>This time we will not observe all four statements rather will go for 2 basic statement which is also valid for primitive data types.</li><li><code>Statement 1</code> is not correct but still works fine. While <code>Statement 4</code> throws an error</li></ul>
<!-- /wp:list -->

```c++
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
exit status 1
error: no viable overloaded '='
  x3 = x2 = x1;     // Statement 4: Meaningful but compiler wont alllow us
  ~~ ^ ~~~~~~~
note: candidate function not viable: no known conversion from 'X *' to 'X &' for 1st argument; dereference the argument with *
  X* operator = (X &rhs){
     ^
1 error generated.
```

<!-- wp:list -->
<ul><li>Probable transformation of <code>Statement 4</code> by the compiler would be</li></ul>
<!-- /wp:list -->

```c++
(X::x3.operator=( ( x2 = x1 ) );
```

<!-- wp:list -->
<ul><li>This will not work simply because of the result of an operation <code>( x2 = x1 )</code> is pointer &amp; copy assignment operator function wants a reference as an argument.</li><li>Now you will say that why we just not change argument with pointer rather than accepting it as a reference. Nice idea! I would say</li></ul>
<!-- /wp:list -->

```c++
X *operator=(X *rhs)
{
    cout << "THIS\n";
    this->var = rhs->var;
    return this;
}
```

<!-- wp:list -->
<ul><li>Now to call above copy assignment operator you need to use the following operation</li></ul>
<!-- /wp:list -->

```c++
x2 = &x1;
```

<!-- wp:list -->
<ul><li>Because we are expecting pointer as an argument in copy assignment operator. <code>x1 = x2</code> or <code>x3 = x2 = x1</code> won't work anymore. </li><li>If you are still getting the correct answer as <code>1 1 1</code> in your output window then just consider print from <code>cout</code>. You are getting the correct answer <code>1 1 1</code> because default copy constructor provided by the compiler is getting called every time. Technically, we have just overloaded copy constructor by changing its return type &amp; argument as a pointer.</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2><strong>Conclusion</strong></h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>Above are the reason why it is not feasible to use <code>pass by value</code> or <code>pointer</code> an argument or <a href="https://stackoverflow.com/questions/3105798/why-must-the-copy-assignment-operator-return-a-reference-const-reference" target="_blank" rel="noreferrer noopener">return type of copy assignment operator</a>.</li><li><strong><em>Compiler designer have designed standard in such a way that your class object operation should also work same as primitive type operations</em></strong> like</li></ul>
<!-- /wp:list -->

```c++
// Primitive type & operations
int a = 5, b, c;
a = b = c;

// User defined type & operations
X x1(5), x2, x3;
x3 = x2 = x1;
```

<!-- wp:block {"ref":4208} /-->