是否应该在return-statement中使用std :: move来提高效率?

时间:2013-05-17 09:31:00

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

我无法弄清楚以下代码中的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

1 个答案:

答案 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;
}

不仅可以移动返回值,而且可以省略移动本身。