简体   繁体   English

Operator ++:引用vs值返回和未使用的参数

[英]Operator++: reference vs value return and unused argument

I saw this C++ code as part of a larger example: 我看到这个C ++代码是一个更大的例子的一部分:

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? 首先,如果Date temp = *this ,那么我不明白为什么返回类型对于这两个函数有什么不同? One returns *this , the other returns temp , which is assigned to *this ? 一个返回*this ,另一个返回temp ,它被分配给*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. 第一个返回this指向的对象作为引用。 That is, the returned object is the object that operator++ is being called on. 也就是说,返回的对象调用operator++的对象。 However, when you do Date temp = *this , temp is copy constructed from the value of *this . 但是,当你执行Date temp = *thistemp是从*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 ). 有两种类型的递增运算符 - 一种是后递增( i++ ),另一种是预递增( ++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. 为了能够单独重载它们(尽管它们具有相同的名称, operator++ ),C ++标准指定后增量运算符采用int类型的参数和未指定的值。 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. 因此,它返回temp副本。

This is an excellent question - it highlights a rather silly design choice the designers of C++ took: 这是一个很好的问题 - 它突出了C ++设计师采用的一种相当愚蠢的设计选择:

  • The overload with no arguments is pre-increment; 没有参数的重载是预先递增的; the overload with an unused int parameter is post-increment. 带有未使用的 int参数的重载是后增量。
  • 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; 添加int参数的原因有一个 - 区分两个重载; 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. 在该代码中, temp保存先前的值, helpIncrement()递增该值,并返回先前的值( temp )。 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) . 编译器知道++my_value应该被翻译成my_value.operator++() ,并且my_value++应该被翻译成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. 第二个函数中未使用的参数区分++运算符的前缀(无参数)和后缀(单个int参数)版本。

This is a basic topic, read about overloading operator++ . 这是一个基本主题,请阅读有关重载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? 首先,如果Date temp = * this,那么我不明白为什么返回类型对于这两个函数有什么不同?

Let's compare this with the situation of ++ on good old int . 让我们将这与旧的int上的++的情况进行比较。 Consider 考虑

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

After this, j holds the old value of i , but i itself is incremented. 在此之后, j保持i的旧值,但是i自己增加了。 So i must have been copied prior to the increment, as if ++ on int were defined as 所以, i必须已经先于增量复制,仿佛++int被定义为

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

OTOH, after OTOH,之后

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

i and j have the same value, so ++ must have been implemented as ij具有相同的值,因此++必须实现为

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. int更改为int&引入便利的地方:不需要复制,并且在需要引用的情况下可以使用++i

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. 这个参数是作为一个语法噱头,所以编译器可以区分两种类型的operator++ (前后增量),但它没有任何明确定义的值。 Giving it a name would trigger an "unused identifier" option in a compiler with proper warnings enabled. 赋予其名称将在编译器中触发“未使用的标识符”选项并启用适当的警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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