提问者:小点点

默认情况下应调用Move构造函数


在以下情况下,我在Integer类中创建了move ctor,我希望在创建Product对象时,默认情况下应该在rvalue引用上调用它,但我只得到了对copy构造函数的调用。 Ubuntu 18上的Gcc-7.5.0

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

在上面的例子中,move调用如果我在产品类ctor中使用dId(std::move(xId)),我希望默认情况下应该在rvalue引用中调用它。 在下面的情况下,我无法避免创建整数类的临时对象,有没有什么好的方法来避免创建临时对象。

    Product(const Integer &xId)
    :dId(xId)
    {

    }
    
    Product(10); // inside main

我对上述问题的目的是建立我的理解,以便我能更好地利用临时对象记忆。


共1个答案

匿名用户

您需要std::move来“传播”rvalue-reference-ness。

在以下函数的主体内部:

void foo(int&& x);

…表达式x是左值int。 而不是int&&

引用并不是真正“存在”的--即使它们是由类型系统支持的,它们应该被视为别名(而不是单独的实体),因此在foo内部使用x就像在foo内部使用原始的,引用的int一样……并且这样做也会创建一个副本,正如您所知。

这将完成工作:

Product(Integer&& xId)
    : dId(std::move(xId))
{}

但是,我实际上鼓励您按值取integer:

Product(Integer xId)
    : dId(std::move(xId))
{}

这样,您也可以使用相同的构造函数来传递lvalueinteger,如果需要,将生成一个副本,如果不需要,则将自动进行移动(例如,通过传递一个文本,这将自动触发对integer的移动构造函数的选择)。