我无法弄清楚以下代码中的std :: move是否有什么好处或完全错误?
类Object
同时定义了Move和Copy构造函数。
首先:使用移动:
template<typename T> template <typename F>
const Object<T> Object<T>::operator*(const F& rhs) const
{
return std::move(Object(*this) *= rhs); // We end in move constructor
}
第二名:没有移动:
template<typename T> template <typename F>
const Object<T> Object<T>::operator*(const F& rhs) const
{
return Object(*this) *= rhs; // We end in copy constructor
}
*=
运算符定义为:
template<typename T> template<typename F>
Object<T>& Object<T>::operator*=(const F& rhs)
{
for(int i = 0; i < dimension ; i++)
{
_inner[i] *= rhs;
}
return *this;
}
以下是我用来测试它的代码:
Object<double> test(4);
Object<double> test2(test * 4);
std::cout << test2; // works fine
结果 在第一个的情况下,我们在移动构造函数中结束,在第二个中,我们以复制构造函数结束。
在任何一种情况下代码都会编译。
一个比另一个更高效,因为我认为将新对象移出而不是将其复制出来会更快吗?
其他信息: 我使用以下编译器:g ++(Ubuntu / Linaro 4.7.3-1ubuntu1)4.7.3
答案 0 :(得分:15)
一个比另一个更高效,因为我认为将新对象移出而不是将其复制出来会更快吗?
是的,假设对象的移动语义比复制更有效,那么在这里使用std::move
会更有效率。
通常,在返回临时变量或局部变量时,将自动使用移动语义。但是,在这种情况下,您不是直接返回临时,而是返回operator*=
返回的左值引用。由于左值不会被移动,因此在这种情况下您需要std::move
将其转换为 rvalue 。
但是,您不应返回const
值,因为这会阻止返回值用于移动初始化(或移动 - 分配)另一个对象。您的示例将通过复制返回值初始化test2
,但该副本可能会被删除。
或者,您可以使用局部变量实现它:
template<typename T> template <typename F>
Object<T> Object<T>::operator*(const F& rhs) const
{
Object lhs(*this);
lhs *= rhs;
return lhs;
}
不仅可以移动返回值,而且可以省略移动本身。