简体   繁体   中英

Operator++: reference vs value return and unused argument

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?

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.

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.

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.

  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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM