2

I have written the following code to demonstrate the move construction. But even though I have used std::move(), move constructor is not being invoked. Can someone please see what is the problem here.

#include "point.hpp"
using namespace std;
class point; 
d2point add_point(d2point&& p1, d2point&& p2) 
{ 
 cout << "inside add point function" << endl;
 d2point z;
 z.setX(p1.getX() + p2.getX());
 z.setY(p1.getY() + p2.getY());
 return z;
} 
int main()
{

 d2point x(2,3);
 d2point y(2,3);

 d2point z = add_point(move(x), move(y));
 z.print_point();
 x.print_point();

 return 0;
}

The following is the code from point.hpp

using namespace std;
class point
{
private:
int x;
public:
point(){cout << "point default constructor gets called" << endl;}
point(int x){ cout << "point param constructor gets called" << endl;
this->x = x;
}   

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

point(point&& other):x(std::move(other.x)) {
cout << "point move constructor gets called" << endl;
}   

int getX(){return x;} 
void setX(int x) { this->x = x; }

virtual void print_point() {}
virtual ~point(){cout << "point destructor gets called" << endl;}
};

class d2point: public point
{
private:
int y;

public:
d2point()
{   
cout << "d2point default constructor gets called" << endl;
}   

d2point(int x, int y):point(x) {
cout << "d2point parameterized constructor gets called" << endl;
this->y = y;
}   

d2point(const d2point& rhs): point(rhs) {
cout << "d2point copy constructor gets called" << endl;
this->y = rhs.y;
}

d2point(d2point&& rhs):point(std::move(rhs)) {
cout << "d2point move constructor gets called" << endl;
this->y = std::move(rhs.y);
rhs.y = 0;
}

int getY(){return y;}
void  setY(int y) { this->y = y; }

void print_point(){
cout << "(" << getX()  << "," << y << ")" << endl;
}

~d2point(){ cout << "d2point destructor gets called" << endl;}
};

The output of the program is as follows:

point param constructor gets called
d2point parameterized constructor gets called
point param constructor gets called
d2point parameterized constructor gets called
inside add point function
point default constructor gets called
d2point default constructor gets called
(4,6)
(2,3)
d2point destructor gets called
point destructor gets called
d2point destructor gets called
point destructor gets called
d2point destructor gets called
point destructor gets called

Here the function which is taking the rvalue reference is being called, but the move constructor statement is not getting printed, it is really called or some other member function is being invoked. Kindly see the problem here.

5
  • 3
    std::move is (approx) a cast to rvalue reference. It doesn't actually do anything itself. Commented Dec 19, 2017 at 12:38
  • @Mat, if that casted rvalue is being passed to the function, then why the move constructor is being invoked to move arguements from x to p1 and y to p2.? Commented Dec 19, 2017 at 12:41
  • 1
    p1 and p2 are references. You wouldn't expect the arguments to be copied if you had add_point(d2point&, d2point&), would you? Same here. Commented Dec 19, 2017 at 12:55
  • What do you expect to gain from "moving" int values? Commented Dec 19, 2017 at 13:07
  • @manni66, this was just for demostration. I got the git of moving instead of copying. Thank you. Commented Dec 19, 2017 at 13:08

1 Answer 1

5

The move constructor will not be called unless you're constructing a new instance of d2point from d2point&&. In your add_point function, you're taking rvalue references to d2point: this means that you're not constructing any new instance, but merely refering to existing ones:

d2point add_point(d2point&& p1, d2point&& p2) 
//                       ^^            ^^

Remember that std::move is just a cast to an rvalue reference.

d2point z = add_point(move(x), move(y));

In the line above, you cast both x and y to d2point&& - they get bound to p1 and p2. No construction happened yet. Finally, you store the result of the add_point call into z. Due to return value optimization it is extremely likely that you won't see a move constructor invoked there either.


Changing add_point to

d2point add_point(d2point p1, d2point p2) 

will definitely invoke d2point::d2point(d2point&&).

Sign up to request clarification or add additional context in comments.

5 Comments

thank you for your answer. Can you please tell me if I have used the correct way to define copy and move constructor for the derived class d2point.
@Ghansham your inheritance is incorrect. d2point is not a kind of point where point is really a d1point. Looking at it another way: this inheritance would make sense if and only if in every place a point is expected you could pass a d2point.
@Ghansham the other issue you are having is that after moving from an object you shouldn't do anything with that object (other than destruct it)
@bolav, yes i should not have used that object, but to check what is the output of that object, I have deliberately put it here. I could have reset the value of x and y in the move constructor, to get the proper feel.
Move operations do not really make sense in the context of fundamental types such as int. Your d2point should honestly be a POD.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.