运算符++:引用与值返回和未使用的参数

Operator++: reference vs value return and unused argument

本文关键字:未使用 参数 返回 引用 运算符      更新时间:2023-10-16

我把这个C++代码看作是一个更大示例的一部分:

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

首先,如果是Date temp = *this,那么我不明白为什么这两个函数的返回类型有什么不同?一个返回*this,另一个返回分配给*thistemp

第二,为什么第二个函数的参数没有变量名?

第一个返回this指向的对象作为引用。也就是说,返回的对象是调用operator++的对象。但是,当执行Date temp = *this时,temp是根据*this的值复制构建的。然后它被复制出函数。从第二个函数中得到的是一个全新的对象。第二个问题的答案解释了为什么函数有这种差异。

增量运算符有两种类型,一种是后增量(i++),另一种是前增量(++i)。为了能够单独重载它们中的每一个(尽管它们具有相同的名称operator++),C++标准指定后增量运算符采用具有未指定值的int类型的参数。这只是为了让您可以在每次使用运算符时重载函数。由于您不太可能想要使用那个未指定的值,所以您也可以不命名它。

现在,预增量操作符的预期行为是,它对对象进行增量,然后计算为该对象。这就是为什么它在这种情况下返回引用。后增量的预期行为是保留原始值的副本,对对象进行增量,然后返回原始值。因此,它返回temp副本。

这是一个很好的问题,它突出了C++的设计者所做的一个相当愚蠢的设计选择:

  • 没有参数的重载是预增量的;带有未使用的CCD_ 15参数的过载是增量后的
  • 这就是为什么增量前的版本可以返回引用,而增量后的版本必须在增加值本身之前复制原始版本
  • 添加int参数的原因只有一个——区分两个过载;它在其他方面毫无意义,这就是为什么它的价值从未被使用过

第一个运算符是预增量:它增加值,并返回结果。第二种是后增量:它增加值,并返回上一个值。在该代码中,temp保持先前的值,helpIncrement()递增该值,并返回先前的值(temp)。参数没有名称的原因是没有使用它。这有点像黑客;编译器知道++my_value应该被翻译成my_value.operator++()并且my_value++应该被翻译到my_value.operator++(1)。也就是说,整型参数的存在与否决定了调用哪个重载。

  1. 第一个函数在递增后返回对它的引用。第二个返回在递增之前的副本。

  2. 第二个函数中未使用的参数区分++运算符的前缀(无参数)和后缀(单个int参数)版本。

这是一个基本主题,阅读有关重载operator++的内容。你可以从这里开始:操作员超载

首先,如果Date-temp=*this,那么我不明白为什么这两个函数的返回类型有什么不同?

让我们将其与旧版int上的++的情况进行比较。考虑

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

此后,j保持i的旧值,但i本身递增。因此,i必须在增量之前复制,就好像int上的++被定义为一样

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

后的OTOH

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

ij具有相同的值,因此++必须实现为

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

intint&的更改带来了便利:不需要复制,并且可以在需要引用的情况下使用++i

其次,为什么第二个函数的参数没有变量名?

因为它永远不应该被使用。该自变量是一个语法噱头,因此编译器可以区分两种类型的operator++(递增前和递增后),但它没有任何定义明确的值。给它一个名称会在编译器中触发一个"未使用的标识符"选项,并启用适当的警告。