i=i++;未定义.是否i=foo(i++)也未定义

i = i++; is undefined. Is i = foo(i++) also undefined?

本文关键字:i++ 未定义 foo 是否      更新时间:2023-10-16

例如:

int foo(int i) { return i; }
int main()
{
  int i = 0;
  i = i++;      // Undefined
  i = foo(i++); // ?
  return 0;
}

当前的ISO C++标准会为这种情况指定什么?

编辑:

以下是我感到困惑的地方:

除非另有说明,否则单独运算符的操作数和单独表达式的子表达式的求值都是无序列的。

如果标量上有副作用对象相对于同一标量对象上的另一个副作用或值计算未排序使用相同标量对象的值,并且它们不可能并发(1.10),则行为为未定义。

在所有情况下,赋值都在值之后排序右操作数和左操作数的计算,以及在赋值表达式的值计算之前

调用函数(包括其他函数调用)中未特别指定的每个求值在被调用函数的主体执行之前或之后排序的是不确定的关于被调用函数的执行。

因此,似乎可以在赋值的左侧进行值计算(仅为i),在右侧进行副作用(从i++修改i),它们彼此之间没有顺序。

EDIT2

对于任何发现自己在这里的人来说,我在这里发现了一个关于测序的非常好的解释。

您引用的最后一句话说"在执行被调用函数体之前或之后没有特别排序",所以问题是增量和赋值是在函数体之前还是之后"特别排序"。

1.9[介绍执行]p15有答案:

调用函数时(无论函数是否内联),每个值的计算和副作用与任何参数表达式或指定被调用函数的后缀表达式关联的是在执行被调用函数体中的每个表达式或语句之前进行排序。[注意:值与不同参数表达式相关的计算和副作用是不按顺序排列的。——尾注]

所以i的增量发生在函数体之前,i的赋值发生在函数返回之后,所以它是完全定义好的。

在C++11之前的术语中,函数调用在增量和赋值之间引入了一个序列点。

i = foo(i++);很好,因为i++是在调用foo()之前执行的。生成i的副本,然后递增i,然后将副本传递给foo()。这与明确地这样做是一样的:

int tmp = i++;
i = foo(tmp);