【问题标题】:Move Constructor is not getting called移动构造函数没有被调用
【发布时间】:2018-06-01 21:38:17
【问题描述】:

我编写了以下代码来演示移动构造。但即使我使用了 std::move(),移动构造函数也没有被调用。谁能看看这里有什么问题。

#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;
}

以下是来自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;}
};

程序的输出如下:

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

这里正在调用正在调用右值引用的函数,但没有打印移动构造函数语句,它确实被调用或正在调用其他一些成员函数。请在这里查看问题。

【问题讨论】:

  • std::move 是(大约)转换为右值引用。它本身实际上并没有做任何事情。
  • @Mat,如果将转换后的右值传递给函数,那么为什么调用移动构造函数将争论从 x 移动到 p1 和 y 到 p2。?
  • p1p2 是引用。如果您有add_point(d2point&amp;, d2point&amp;),您不会期望参数被复制,对吗?这里也一样。
  • 您希望从“移动”int 值中获得什么?
  • @manni66,这只是为了演示。我得到了移动而不是复制的 git。谢谢。

标签: c++ c++11 constructor move-constructor


【解决方案1】:

除非您从d2point&amp;&amp; 构造d2point 的新实例,否则不会调用移动构造函数。在您的 add_point 函数中,您将 rvalue references 带到 d2point:这意味着您没有构建任何新实例,而只是引用现有实例:

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

请记住,std::move 只是对右值引用的强制转换。

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

在上面的行中,您将xy 都转换为d2point&amp;&amp; - 它们被绑定到p1p2。还没有施工。最后,将add_point 调用的结果存储到z。由于返回值优化,您极有可能不会看到那里调用了移动构造函数。


add_point 更改为

d2point add_point(d2point p1, d2point p2) 

肯定会调用d2point::d2point(d2point&amp;&amp;)

【讨论】:

  • 感谢您的回答。你能告诉我我是否使用了正确的方法来为派生类 d2point 定义复制和移动构造函数。
  • @Ghansham 您的继承不正确。 d2point 不是 point 的一种,point 实际上是 d1point。换个角度看:当且仅当在每个地方都需要point,您可以传递d2point,这种继承才有意义。
  • @Ghansham 您遇到的另一个问题是,从一个对象移动后,您不应该对该对象执行任何操作(除了破坏它)
  • @bolav,是的,我不应该使用那个对象,但是为了检查那个对象的输出是什么,我故意把它放在这里。我可以在移动构造函数中重置 x 和 y 的值,以获得正确的感觉。
  • 移动操作在 int 等基本类型的上下文中没有真正意义。你的 d2point 应该是一个 POD。
猜你喜欢
  • 2016-07-12
  • 1970-01-01
  • 2019-05-27
  • 2017-09-19
  • 1970-01-01
  • 2011-05-22
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多