In following case where i have created move ctor in Integer class, i am expecting that it should be called by default on rvalue reference while creating Product object but i am getting call of copy constructor only. Gcc - 7.5.0 on Ubuntu 18
#include<iostream>
using namespace std;
class Integer
{
int *dInt = nullptr;
public:
Integer(int xInt) {
dInt = new int(xInt);
cout<<"Integer Created"<<endl;
}
Integer(const Integer &xObj)
{
cout<<"Copy called"<<endl;
dInt = new int(xObj.mGetInt());
}
Integer(Integer &&xObj)
{
cout<<"Move called"<<endl;
dInt = xObj.dInt;
xObj.dInt = nullptr;
}
Integer& operator=(const Integer &xObj)
{
cout<<"Assignment operator called"<<endl;
*dInt = xObj.mGetInt();
return *this;
}
Integer& operator=(Integer &&xObj)
{
cout<<"Move Assignment operator called"<<endl;
delete dInt;
dInt = xObj.dInt;
xObj.dInt = nullptr;
return *this;
}
~Integer()
{
cout<<"Integer destroyed"<<endl;
delete dInt;
}
int mGetInt() const {return *dInt;}
};
class Product
{
Integer dId;
public:
Product(Integer &&xId)
:dId(xId)
{
}
};
int main ()
{
Product P(10); // Notice implicit conversion of 10 to Integer obj.
}
In above case, move called if i use dId(std::move(xId)) in Product class ctor, I was expecting it should called by default on rvalue reference. In following case i couldn't avoid creating of temporary object of Integer class, Is there any good way to avoid creating of temporary object.
Product(const Integer &xId)
:dId(xId)
{
}
Product(10); // inside main
My purpose of above question to build my understanding so that i can utilize temporary object memory better.
You need std::move
to "propagate" rvalue-reference-ness.
Inside the body of the following function:
void foo(int&& x);
…an expression x
is an lvalue int
. Not int&&
.
References don't really "exist" — even though they are powered by the type system, they are supposed to be treated as aliases (rather than separate entities), so using x
inside foo
is treated just like using the original, referred-to int
inside foo
… and doing that would also create a copy, as you know.
This will do the job:
Product(Integer&& xId)
: dId(std::move(xId))
{}
However, I actually encourage you to take Integer
by value:
Product(Integer xId)
: dId(std::move(xId))
{}
That way, you can use the same constructor for passing lvalue Integer
too, and a copy will be produced if necessary, whereas a move will happen automatically if not (e.g. by passing in a literal, which will automatically trigger selection of Integer
's move constructor).