如何使用移动语义重载一元算术

时间:2019-04-24 16:42:40

标签: c++ operator-overloading

我想用std :: vector的移动语义实现一元算术运算符。目的是避免将运算符内部应用到右值时对其进行内部分配。

问题:以下操作无法编译:c =-(a + b)

之所以无法编译,是因为我为std :: vector实现的二进制算术运算符+我返回了const lvalue(这样编译器将抱怨(a + b)= c,这没有意义)

二进制+运算符

template<class T, class AllocVect1, class AllocVect2>
inline const std::vector<T> operator+ (
    const std::vector<T, AllocVect1> &v1,
    const std::vector<T, AllocVect2> &v2) {
    std::vector<T> vout;

    *Compute vout = v1 + v2*

    return vout;
}

一元运算符

template<class T, class Alloc>
inline const std::vector<T>& operator- (std::vector<T, Alloc> &&v) {
    std::transform (
        v.begin (), 
        v.end (), 
        v.begin (), 
        [](const auto &val){return -val;});
    return v;
}

1 个答案:

答案 0 :(得分:0)

通过值传递并返回向量。

听起来似乎不合常理,一旦您考虑了以下因素,便会变得有意义:

  1. 可以将临时对象隐式地移动到一个值参数中-不发生复制。这就像您要在局部变量上调用std::move

  2. 由于该对象(参数)没有const限定符,因此可以就地修改。

  3. 可以返回修改后的对象,并再次隐式应用移动语义。永远不要返回对局部变量的引用-左值引用或右值引用都不能。

template<class T>
std::vector<T> operator-(std::vector<T> v) { // 1.
    std::for_each( // 2.
        v.begin(), 
        v.end(), 
        [](T& val) {val = -val;});

    return v; // 3.
}

可以同时使用rvalues(移动+修改+移动)和lvalues(复制+修改+移动)来调用此运算符。

话虽这么说,const Param&Param&&的单独重载有 的优点,其详细信息已在单独的答案中进行了解释: