i = i ++; 未定义.i = foo(i ++)也未定义吗?

Jus*_*tin 16 c++ undefined-behavior

例如:

int foo(int i) { return i; }

int main()
{
  int i = 0;

  i = i++;      // Undefined
  i = foo(i++); // ?

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当前的ISO C++标准将针对此案例指定什么?

编辑:

这是我感到困惑的地方:

除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的评估是不确定的.

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

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

调用函数(包括其他函数调用)中的每个评估(在执行被调用函数的主体之前或之后没有特别排序)对于被调用函数的执行是不确定地排序的.

因此,似乎你可以在赋值的左侧进行值计算(只是i),并且右侧的副作用(ifrom 的修改i++)不会相互排序.

编辑2:

对于那些发现自己的人来说,我在这里找到关于测序的非常好的解释.

Jon*_*ely 15

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

1.9 [intro.execution] p15有答案:

当调用函数时(无论函数是否为内联函数),与任何参数表达式相关联的每个值计算和副作用,或者使用指定被调用函数的后缀表达式,都会在执行每个表达式或语句之前对其进行排序.叫功能.[ 注意:与不同参数表达式相关的值计算和副作用未被排序.- 结束说明 ]

因此增量i发生在函数体之前,并且赋值i发生在函数返回之后,因此它是完全明确定义的.

在pre-C++ 11术语中,函数调用引入了增量和赋值之间的序列点.


Rem*_*eau 11

i = foo(i++);很好,因为i++foo()被调用之前执行.副本i由,i进行增量,那么,副本将传递给foo().它与明确地这样做是一样的:

int tmp = i++;
i = foo(tmp);
Run Code Online (Sandbox Code Playgroud)