10

Can I use:

MyClass& MyClass::operator++ () {
    a++;  // private var of MyClass
    return (*this);
}

Or it can be:

MyClass MyClass::operator++ ();

What's the difference?


Thanks for answers. I have another issue.

Many people do something like that:

MyClass& MyClass::operator++();
MyClass MyClass::operator++(int);

Isn't it illogical? Please give some examples if you can.

I know that the first version is pre-increment and the second is post-increment, but i ask why the first one returns reference but the second one not? It is in the same code (class), and the same use of the code.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
name3r123
  • 163
  • 1
  • 1
  • 6
  • Good question. I'm still waiting for an answer that says why the second one **won't** work. – Mark Ransom Jun 16 '11 at 17:03
  • 1
    @Mark, you'll have to wait a long time. The second one will work just fine. This is actually a design question - what *should* he do, not what *must* he do. He probably *should* return a reference, but he *may* do an infinite variety of other things, including his second example. – Robᵩ Jun 16 '11 at 17:06
  • @Rob, your answer was the one I was hoping to see - you already have my +1. – Mark Ransom Jun 16 '11 at 17:10
  • name3r, you should get a C++ book. Your question are one of the basic ones, a book should answer them. That said, the first version is for preincrement, while the second is for postincrement (dummy-int parameter). – Xeo Jun 16 '11 at 17:13
  • 1
    As to your second question, the post-increment doesn't return a reference because that wouldn't model the operator correctly. post-increment returns the *prior* value not the *current* value. Returning a reference would, by definition, return the current value. – Robᵩ Jun 16 '11 at 17:25
  • Please don't ask an additional question within the same post after receiving answers for the first. Put them in a new post instead. – Jamal Sep 15 '15 at 02:01

5 Answers5

20

No, you don't have to return the reference to your object when you overload the pre-increment operator. In fact you may return anything you'd like, MyClass, int, void, whatever.

This is a design issue -- you must ask yourself what is the most useful thing to the users of your class that you are able to return.

As a general rule, class operators are the most useful when they cause the least confusion, that is, when they operate the most like operators on basic types. In this case, the pre-increment operator on a basic type:

int  i = 7;
j = ++i;

increments the variable and then returns the new value. If this is the only use you want MyClass to have, then returning a copy of your class is sufficient.

But, the pre-increment operator on a basic type actually returns an lvalue. So, this is legal:

int i = 7;
int *p = &++i;

If you want to support an operation like this, you must return a reference.

Is there a specific reason that you don't want to return a reference? Is that not a well-formed concept for your particular class? If so, consider returning void. In that case, this expression: ++myObject is legal, while this myOtherObject = ++myObject is not.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
3

You can return whatever you want. void, reference to self, copy of self, something else. Whichever you prefer (or need).

If you plan using the ++ operator in chained expressions (like (++obj).something()) then return a reference. In you don't, then void is just fine.

Remember that in the end, operators are just like normal methods: you can do whatever you want with them, provided you respect their prototype.

user703016
  • 37,307
  • 8
  • 87
  • 112
  • 1
    @name3 - The best way is to do what seems logical for your class. You don't even have to increment the value, you could just as well multiply by 42 if that is the *obvious* thing to do for your type. For example, boost::filesystem overloads `operator/` to concatenate paths instead of using it for division. – Bo Persson Jun 16 '11 at 19:31
3

For question two:

Prefix returns a reference, as expected. Postfix returns a copy to be consistent with the behavior of the postfix operator(s).

Break it down simply to int:

int c = 0;

if(++c)
{
   // true, prefix increments prior to the test
}

c = 0;

if(c++)
{
   // false, c now == 1, but was incremented after the test
}

Implementing this behavior in a class requires a copy be returned because the postfix operator will have modified the state of the object.

If the program does not need true postfix operation, you are free of course to implement how you wish. While there are standard ways of writing these operators (that are understood by most C++ programmers), there's nothing actually stopping you from implementing this in different ways.

The argument provided about incorrect functionality surrounding (obj++)++ is not really important, as that code won't even compile for POD types (in Visual Studio 2010, at least), because for POD types, a copy is returned and that temporary copy cannot be used alone as an l-value.

However, for the prefix operator a reference is the preferred return as that allows the proper behavior for chaining the operation (++(++obj)).

Chad
  • 18,706
  • 4
  • 46
  • 63
2

Its not compulsory, but we should try to make operator overloading intuitive and it should work as per the operator which is being overloaded.

If we do int i = 10; i++ = 0 Then second statement is not allowed it says it requires lvalue as i++ denotes older state of i not a storage ... while ++i = 0 perfectly works fine .. so just to keep it in sync with actual operators prefix version had to return refence so that its return value may be treated as lvalue in expressions.

shashank
  • 29
  • 1
  • `++i = 0` does not work perfectly fine and suffers from similar problems as `i++ = 0`. A variable may be set only once per sequence point. "The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point." – Dan Feb 19 '12 at 07:29
1

Yes, you should return by reference. No need for the parenthesis around *this.

EDIT: Replying to your comment... You don't have to return by reference. But in general we follow some guidelines which make our classes behave "as expected" when compared to the builtin semantics of such operators. You might wanna take a look at http://www.parashift.com/c++-faq-lite/operator-overloading.html.

Leandro T. C. Melo
  • 3,974
  • 22
  • 22