默认情况下应调用移动构造函数
Move constructor should be called by default
在以下情况下,我在 Integer class 中创建了 move ctor,我希望在创建 Product 对象时默认在右值引用上调用它,但我只会调用复制构造函数。
Gcc - Ubuntu 18
上的 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.
}
在上述情况下,如果我在 Product class ctor 中使用 dId(std::move(xId)),则移动被调用,我期望它应该默认在右值引用上调用。
在以下情况下,我无法避免创建 Integer class 的临时对象,有什么好的方法可以避免创建临时对象。
Product(const Integer &xId)
:dId(xId)
{
}
Product(10); // inside main
我提出上述问题的目的是为了加深理解,以便更好地利用临时对象内存。
您需要 std::move
来“传播”右值引用特性。
在以下函数体内:
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))
{}
这样,您也可以使用相同的构造函数来传递左值 Integer
,并且会生成一个副本如果需要,而如果不是(例如,通过传入文字,这将自动触发选择 Integer
的移动构造函数)。
在以下情况下,我在 Integer class 中创建了 move ctor,我希望在创建 Product 对象时默认在右值引用上调用它,但我只会调用复制构造函数。 Gcc - Ubuntu 18
上的 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.
}
在上述情况下,如果我在 Product class ctor 中使用 dId(std::move(xId)),则移动被调用,我期望它应该默认在右值引用上调用。 在以下情况下,我无法避免创建 Integer class 的临时对象,有什么好的方法可以避免创建临时对象。
Product(const Integer &xId)
:dId(xId)
{
}
Product(10); // inside main
我提出上述问题的目的是为了加深理解,以便更好地利用临时对象内存。
您需要 std::move
来“传播”右值引用特性。
在以下函数体内:
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))
{}
这样,您也可以使用相同的构造函数来传递左值 Integer
,并且会生成一个副本如果需要,而如果不是(例如,通过传入文字,这将自动触发选择 Integer
的移动构造函数)。