6

特别是,前缀运算符的按引用返回对我来说很有意义——它很有用,以防人们想对对象进行进一步的操作。

但是,我无法理解为什么后缀运算符被设计为按值返回。

它仅仅是一个约定,还是有充分的理由为什么它是这样设计的(比如按值返回对后缀没有意义,但对前缀有意义)?

有人可以解释吗?

回答

多亏了下面的答案,后缀运算符似乎不一定要按值返回(根据标准)。

但是,由于后缀运算符的语义要求(返回原始值,但之后增加对原始值的引用),结合标准要求:

运算符重载是函数,因此所有副作用都必须在函数完成之前发生。

正如下面David Rodriguez清楚地解释的那样,分叉值似乎是语义要求的必然结果。

在这种情况下,由于我们正在返回另一个值(不是原始引用,因为它会被函数的右括号改变),按值返回另一个值似乎是最有意义的。

4

4 回答 4

12

后缀运算符是产生原始值然后修改对象的表达式。同时,运算符重载是函数,因此所有副作用都必须在函数完成之前发生。获得所需语义的唯一方法是在应用更改之前复制对象的初始状态。原始状态必须按值返回(如果返回引用,则表达式的评估将在函数完成后产生对象的状态,因此具有前缀运算符的语义,而不是后缀运算符)

于 2013-02-12T05:13:45.590 回答
5

这是约定,因为 post fix 的典型实现涉及创建函数本地的临时对象,同时使用前缀运算符递增最初传递的对象,然后返回临时对象。您不能返回对该本地对象的引用,因此它需要按值返回。

您不能返回引用,因为本地对象只能在函数的范围内保证是活动的,并且超出此范围的任何访问都将导致未定义的行为。

于 2013-02-12T04:37:56.920 回答
3

以下代码在 C 和 C++ 中定义良好:

int i = 7;
printf("%i\n", i++ + 2);

这会将 9 打印到控制台,而i将是 8。保证。

后缀增量/减量修改i,但它们返回 的i值。对对象执行此操作的唯一方法是将当前值保存为新值,自增,然后返回保存的值。

于 2013-02-12T04:38:48.187 回答
3

当然这是一个很好的理由。后增量运算符执行以下操作:

  1. 递增变量和
  2. 返回其旧值。

无法返回对变量“旧值”的引用。它消失了。

于 2013-02-12T05:01:46.083 回答