3

I often see my teachers use const operator +-*/ which return const value. Is it a good practice to do that? Should I do that for every class I write? (T means any struct/class that overloads operator +-*/).

For example:

struct Fraction
{
    //something here.
    const Fraction operator+(const Fraction &rhs) const;
    const Fraction operator-(const Fraction &rhs) const;
    const Fraction operator*(const Fraction &rhs) const;
    const Fraction operator/(const Fraction &rhs) const;
};
Niall
  • 30,036
  • 10
  • 99
  • 142
acx_cosmos
  • 33
  • 4
  • 5
    `const Student` in return makes little sense – marcinj Oct 16 '14 at 10:34
  • 2
    It makes little sense to return `const`, and it impedes move semantics. – juanchopanza Oct 16 '14 at 10:35
  • Your title is different to your code sample – M.M Oct 16 '14 at 10:36
  • 1
    For reference: [Operator overloading](http://stackoverflow.com/questions/4421706/operator-overloading) – moooeeeep Oct 16 '14 at 10:42
  • 3
    I can sort of understand *multiplying* students (even though the result usually doesn't become a student until years later) but what kind of student do you get if you *divide* one student by another? – molbdnilo Oct 16 '14 at 11:00
  • +1 molldbnilo. You should only overload operators when there is a clear unambiguous definition of what the operator means in the domain. I cannot imagine what the different arithmetic operators could do with a pair of input `Student` objects, so make the operations named functions with a meaningful name of what they do. – David Rodríguez - dribeas Oct 16 '14 at 11:05
  • 1
    I do agree that "Student" made little sense. Changed it to "Fraction". – acx_cosmos Oct 16 '14 at 13:01

2 Answers2

6

No, it's a bad idea since it inhibits move semantics. In the following:

a = b + c;

the temporary result of b + c can be moved to a if not const, but must be copied if it is const. Copying is often a more expensive operation than moving.

Historically, in the days before move semantics, it was suggested to prevent nonsense like (a + b) = c. Some argued that it was better to make that cause a compile-time error rather than strange run-time behaviour. These days, even if you agree with that argument, doing so comes with a cost.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

The const on the return type is not needed (in general and in this case). The return is an rvalue, modifying it could make sense, it could not, but in general return types (by value) are not const. This is contrasted to returning references, where const can make a bigger difference.

Assuming C++11 is being used, the return type being const Fraction would interfere with the usual move semantics.

When considering the overloading of the arithmetic operators (+, -, * and /), following the canonical form of the built in operators is recommended. Return the result by modifiable rvalue, i.e. not const. For the assignment versions of these operators (+=, -=, *= and /=), return the value by reference (it would generally be *this).

As follows;

T T::operator+(const T2 &b) const;
// and
T& T::operator+=(const T2& b);

The const on the member methods here make good sense, the object itself would not be expected to be altered (in a general sense), so marking them as const is recommended.

Niall
  • 30,036
  • 10
  • 99
  • 142