Overloading operator-() in C++

2020-05-10 03:53发布

问题:

I am trying to convert the following function to include - sign instead of a subtract function. But it says function not viable and expects an lvalue for the 1st argument.

class fraction
{
    long num;
    long den;
}

I have excluded the constructor and everything else.

inline fraction fraction::operator+(fraction &f)
{
    fraction t;
    t.num = num - f.num;
    t.den = den - f.den;
    return t;
}
inline const fraction sub(const fraction& f,const fraction& s)
{
    return fraction (getNum(f)*getDen(s)-getDen(f)*getNum(s),getDen(f)*getDen(f));
}

回答1:

Herb Sutter's article teaches us to implement a member subtract-assign operator first, and then implement the non-member subtraction operator in terms of it.

So, I would suggest things like this:

class fraction
{
    long num;
    long den;

public:
    fraction& operator-=(const fraction& rhs)
    {
        [[Underlying operations]]
        return *this;
    }
};

inline fraction operator-(fraction lhs, const fraction& rhs)
{
    lhs -= rhs;
    return lhs;
}

The member subtract-assign operator modifies the object itself, and then return itself by reference as the convention.

The non-member subtract take the left-hand-side by value, since we need to create a new one. It takes rhs by const lvalue reference, as we are just observing it. The subtraction is actually done by the subtract-assign operator. It returns lhs by value.

Don't return local object by reference. Doing so is undefined behaviour. Return by reference only when the object lives longer than the function, e.g. the member subtract-assign operator.

Since you mention some trouble involving lvalue, I should mention that const lvalue reference (const T&) can refer to both lvalue and rvalue, but non-const lvalue reference (T&) can only refer to lvalue. I suggest you to look up "lvalue" and "rvalue" and "lvalue reference" and "rvalue reference" on the Internet for details, and it can be complicated.


With comment disfavouring pass-by-value concerning Return Value Optimization and other issues, you may also consider taking lhs by const reference and make a local copy.

inline fraction operator-(const fraction& lhs, const fraction& rhs)
{
    fraction local_copy = lhs;
    local_copy -= rhs;
    return local_copy;
}