0

I wrote this simple code to understand the functionality of copy constructor in c++. When I initialize "obj2" with "obj1" directly it is working fine. But when I try to initialize "obj2" with the returning object from the function "func()" it is showing an error:

error: cannot bind non-const lvalue reference of type 'MyInt&' to an rvalue of type 'MyInt'

Why is this happening?

Code:

#include<bits/stdc++.h>
using namespace std;

class MyInt
{
    int x;
public:
    MyInt()
    {
       cout<< "default constructor called" << endl;
    }
    MyInt(int x)
    {
        cout<< "constructor with initializer called" << endl;
        this->x = x;
    }
    MyInt(MyInt& obj) {
        this->x = obj.x;
        cout<< "copy constructor called" << endl;
    }
    ~MyInt()
    {
        cout<< "destructor called" << endl;
    }
};

MyInt func(MyInt obj)
{
    return obj;
}

int main()
{
    MyInt ob1(2);
    //MyInt ob2 = ob1;      //works perfectly fine: "copy constructor called"
    MyInt ob2 = func(ob1);  //giving error
}
  • 6
    Note that your copy constructor has the form `MyInt(MyInt& obj)` not `MyInt(const MyInt& obj)`. In C++, you [cannot](https://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object?rq=1) bind a pure rvalue like the return of `func()` to a non-const lvalue reference. – Nathan Pierson Sep 10 '21 at 20:41
  • I think I'm missing out on this one because of mandatory copy elision. – user4581301 Sep 10 '21 at 20:42
  • 1
    Unrelated: Obligatory link to [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) But if you use it anyway and combine it with using namespace std;, [things can get really weird](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). – user4581301 Sep 10 '21 at 20:45
  • 3
    Perhaps you could explain what you _do_ and _don't_ understand about the error message? Any answer to "Why?" is likely going to be an attempt to guess how to rephrase that message. Do you know what an rvalue is? Do you know that it can't be bound to a non-const reference such as `MyInt&`? – Drew Dormann Sep 10 '21 at 20:48

1 Answers1

1

You have defined this constructor:

MyInt(MyInt& obj) {
    this->x = obj.x;
    cout<< "copy constructor called" << endl;
}

The parameter MyInt& obj is a reference, and it is not const.

This indicates that you wish to be able to both read from it and write to it.

C++ will protect you from certain mistakes by not allowing a temporary (also called an "rvalue") to be passed as this parameter. Because writing to a temporary is almost certainly a mistake. Whatever you write will get lost.

Your function, however, does not write to that parameter. You can indicate that you don't intend to write to a reference by making it const.

MyInt(const MyInt& obj) {
    this->x = obj.x;
    cout<< "copy constructor called" << endl;
}

This change will allow temporaries to be passed to this constructor.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180