2

I saw this C++ code as part of a larger example:

Date &Date::operator++()
{
    helpIncrement();
    return *this;
}

Date Date::operator++( int )
{
    Date temp = *this;
    helpIncrement();
    return temp;
}

Firstly if Date temp = *this, then I dont see why the return type is any different for these two functions? One returns *this, the other returns temp, which is assigned to *this?

Secondly, why does the parameter for the second function not have a variable name?

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
user997112
  • 29,025
  • 43
  • 182
  • 361
  • 1
    see also [this question](http://stackoverflow.com/q/3846296/212858) and [this question](http://stackoverflow.com/q/6375697/212858) ... in fact probably [most of these](http://stackoverflow.com/search?q=%5Bc%2B%2B%5D+increment+operator) – Useless Dec 09 '12 at 21:21
  • @Useless sorry, didn't realise it was specific to the post increment – user997112 Dec 09 '12 at 21:21
  • No problem, the links were just for information. I didn't vote to close as duplicate because you got useful answers, making this a useful reference in itself. – Useless Dec 09 '12 at 21:23

5 Answers5

6

The first returns the object pointed to by this as a reference. That is, the returned object is the object that operator++ is being called on. However, when you do Date temp = *this, temp is copy constructed from the value of *this. It is in turn then copied out of the function. What you get from the second function is a whole new object. Why the functions have this difference is explained in the answer to your second question.

There are two types of increment operator - one is post-increment (i++) and the other is pre-increment (++i). To be able to overload each of them individually (despite them having the same name, operator++), the C++ standard specifies that the post-increment operator takes an argument of type int with unspecified value. This is simply so that you can overload the function for each use of the operator. Since you're unlikely to want to use that unspecified value, you may as well just leave it unnamed.

Now, the expected behaviour of the pre-increment operator is that it increments the object and evaluates to then be that object. That's why it returns a reference in this case. The expected behaviour of post-increment is that it keeps a copy of the original value, increments the object and then returns the original value. Hence, it returns the temp copy.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
1

This is an excellent question - it highlights a rather silly design choice the designers of C++ took:

  • The overload with no arguments is pre-increment; the overload with an unused int parameter is post-increment.
  • That is why the pre-increment version can return a reference, while the post-increment must make a copy of the original before incrementing the value itself.
  • The int parameter is added for a single reason - distinguishing between the two overloads; it is otherwise meaningless, that is why its value is never used.
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 3
    "silly" is in the eye of the beholder. How would you have done it? – Pete Becker Dec 09 '12 at 21:08
  • @PeteBecker Several choices come to my mind: a set of keywords `preincrement`/`postincrement`/`predecrement` and `postdecrement` sound like a reasonably clean choice. – Sergey Kalinichenko Dec 09 '12 at 21:11
  • 3
    @dasblinkenlight Introducing new keywords gives the WG21 members restless nights. – Joseph Mansfield Dec 09 '12 at 21:14
  • @dasblinkenlight - well, maybe, but that means taking away identifiers that might already be in use, plus creating an exception, for `++` and `--`, to how operators are defined. While that might be viable in some people's eyes, it certainly doesn't make the chosen syntax silly. – Pete Becker Dec 09 '12 at 21:16
  • @sftrabbit I understand. That choice has been made back in the eighties or early nineties; the train has left on changing it now. – Sergey Kalinichenko Dec 09 '12 at 21:16
  • @PeteBecker I understand your point, and I do agree that it is too late to change it now. But when they originally made that decision, they had a lot more latitude for the change. – Sergey Kalinichenko Dec 09 '12 at 21:18
  • @dasblinkenlight - not really. Compatibility with C code was and is important. Adding keywords is always a problem. – Pete Becker Dec 09 '12 at 21:32
  • @PeteBecker Well, they managed to sneak in *some* keywords in addition to C - `class`, `private`, `protected`, and so on. That's when they could have added a few more to avoid a "solution" that borders on a hack. – Sergey Kalinichenko Dec 09 '12 at 21:39
  • 1
    @dasblinkenlight - making the syntax for `++` and `--` different from the syntax for all the other operators doesn't sound like a good idea. Overloading works, and it's consistent. – Pete Becker Dec 09 '12 at 21:42
  • @PeteBecker There are no other operators like `++` and `--`, so there is nothing else with which to make them consistent. To me, re-purposing the overload to resolve between the pre- and post-increment operators remains the exemplary hack that I've seen in a syntax of any mature programming language. – Sergey Kalinichenko Dec 09 '12 at 22:30
  • @dasblinkenlight - there are other **operators**, and the handling of `++` and `==` is consistent with how **operators** are handled. – Pete Becker Dec 09 '12 at 22:33
  • @PeteBecker I am talking about pairs of prefix and postfix operators. While the overrides of prefix operators is consistent with the way other operators are handled, the `int` hack is invented specifically for the `++` and `--` pairs. – Sergey Kalinichenko Dec 10 '12 at 00:15
  • @dasblinkenlight - yes, I know you're trying to distinguish `++` and `--` from other operators. I don't buy it. – Pete Becker Dec 10 '12 at 14:13
  • @PeteBecker One doesn't have to "buy it", because it is an objective truth and not a matter of an opinion: there are simply no other operators in the language that allow different overrides in prefix vs. postfix position. Language designers had other options, besides introducing new keywords. For example, using `Date::++operator` vs. `Date::operator++` syntax would be very intuitive. That would require one hell of a nasty change to the parser, though. I think that what they did in the end was taking the road of least resistance. – Sergey Kalinichenko Dec 10 '12 at 14:31
  • @dasblinkenlight - oh, please. Your assertion that the design choice was "silly" is not objective truth, it is opinion. – Pete Becker Dec 10 '12 at 14:32
  • @PeteBecker "you're trying to distinguish `++` and `--` from other operators" is the statement to which I am referring in my "objective truth vs. a matter of opinion" comment. My description of the decision to re-purpose a parameter-based overload as a "silly design choice" is, undoubtedly, quite far from being an objective truth - it is definitely my opinion. – Sergey Kalinichenko Dec 10 '12 at 14:54
1

The first operator is pre-increment: it increments the value, and returns the result. The second is post-increment: it increments the value, and returns the previous value. In that code, temp holds the previous value, helpIncrement() increments the value, and the previous value (temp) is returned. The reason the argument doesn't have a name is that it isn't used. That's a bit of a hack; the compiler knows that ++my_value should get translated into my_value.operator++(), and that my_value++ should get translated into my_value.operator++(1). That is, the absence or presence of an integral argument determines which overload to call.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1
  1. The first function returns reference to this, after it was incremented. The second one returns a copy of this, before it was incremented.

  2. The unused parameter in the second function distinguishes between prefix (no parameter) and postfix (single int parameter) versions of ++ operator.

This is a basic topic, read about overloading operator++. You can start here: Operator overloading

Community
  • 1
  • 1
v154c1
  • 1,698
  • 11
  • 19
1

Firstly if Date temp = *this, then I dont see why the return type is any different for these two functions?

Let's compare this with the situation of ++ on good old int. Consider

int i = 1;
int j = i++;

After this, j holds the old value of i, but i itself is incremented. So i must have been copied prior to the increment, as if ++ on int were defined as

class int { // pseudocode
  public:
    int operator++(int)
    {
        int temp = *this;
        *this += 1;
        return temp;
    }
};

OTOH, after

int i = 1;
int j = ++i;

i and j have the same value, so ++ must have been implemented as

int &operator()
{
    *this += 1;
    return *this;
}

where the change from int to int& introduces convenience: there's no need to make a copy and it's possible to use ++i in a situation where a reference is needed.

Secondly, why does the parameter for the second function not have a variable name?

Because it should never be used. The argument is there as a syntactic gimmick so the compiler can distinguish the two types of operator++ (pre- and post-increment) from each other, but it doesn't have any well-defined value. Giving it a name would trigger an "unused identifier" option in a compiler with proper warnings enabled.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836