C++ 是int a=++;i+++;我的行为不明确?

C++ 是int a=++;i+++;我的行为不明确?,c++,c++17,language-lawyer,undefined-behavior,sequencing,C++,C++17,Language Lawyer,Undefined Behavior,Sequencing,考虑以下代码: intmain(){ int i=0; int a=++i++i; } 我找不到任何说明+的操作数未排序的信息。因此,根据标准,二进制+的操作数序列是不确定的 给定任意两个评估A和B,如果A在B之前排序(或相当于,B在A之后排序),则A的执行应在B的执行之前。如果A未在B之前排序,且B未在A之前排序,则A和B未排序。[ 注意:未排序评估的执行可能重叠。 — 尾注 ] 当A在B之前排序或B在A之前排序时,评估A和B的排序是不确定的,但未指定是哪个[ 注意:不确定顺序的评估

考虑以下代码:

intmain(){
int i=0;
int a=++i++i;
}
我找不到任何说明
+
的操作数未排序的信息。因此,根据标准,二进制
+
的操作数序列是不确定的

给定任意两个评估A和B,如果A在B之前排序(或相当于,B在A之后排序),则A的执行应在B的执行之前。如果A未在B之前排序,且B未在A之前排序,则A和B未排序。[ 注意:未排序评估的执行可能重叠。 — 尾注 ]

当A在B之前排序或B在A之前排序时,评估A和B的排序是不确定的,但未指定是哪个[ 注意:不确定顺序的评估不能重叠,但可以先执行其中任何一个。 — 尾注 ]

引号表示A的评估可以发生在B之前,或者B的评估可以发生在A之前。未排序的评估的执行可以重叠,而不确定排序的评估不能重叠,这是不同的

我们知道,由于前缀
++
的原因,
i
的修改总是发生在
i
的值计算之前

然后根据规则:

表达式(或子表达式)的评估通常包括值计算(包括确定用于glvalue评估的对象的标识并获取先前分配给对象用于prvalue评估的值)和副作用的启动

如果一个内存位置上的副作用相对于同一内存位置上的另一个副作用或使用同一内存位置中任何对象的值进行的值计算是不排序的,并且它们可能不是并发的,则该行为是未定义的

因此,无论A的求值是在B之前还是相反,都没有与相应的值计算相关的副作用,也没有与
++i++++i;
相关的副作用。因为不确定顺序的求值不能重叠,所以两个求值中的一个必须在另一个之前完全执行。求值包括数值计算和副作用。因此,
i
的一个增量比另一个增量先计算

但是,未排序的求值遵循不同的规则,因此,如果二进制
+
操作数的求值是未排序的,而不是不确定的顺序,那么混淆将得到解决。如果我在上述分析中遗漏了标准中的某些内容,请更正

使现代化 我发现了下面这句话,它似乎表明评估是不连续的:

除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是不排序的

然而,我不知道如何正确理解这个句子。我想出了两种解释:

对于运算符A,A的操作数的求值是 互不排序;对于表达式B,的求值 B的子表达式彼此不排序

将单个运算符的操作数的求值取为。取 B.A为单个表达式的子表达式的求值 以B不排序

哪种解释是正确的?

标准文本似乎暗示行为未定义

  • +
    中,
    的求值是不排序的2,3
  • 这两个部分有副作用,影响相同的内存位置
(1) 在我看来,这一部分是明确的,但我不确定是否有其他部分说的是相反的或更高层次的概念(例如,什么是程序的执行)由于矛盾的规则,逻辑上没有被打破。考虑到C++的复杂性,我实际上会很惊讶没有出现错误。 (2) 在重载的
运算符+
的情况下,它们将被不确定地排序(因为规则与函数调用的规则相同,因此不是未定义的行为:N4713的8.5.1.2[5]后缀表达式在表达式列表中的每个表达式和任何默认参数之前排序。参数的初始化,包括每个关联的值计算和副作用,是不确定的 相对于任何其他参数的排序”),但对于本机
int
s,这不适用,且行为未定义


(3) 正文中说“除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是不排序的”。当然,对于一元运算符来说,这个问题是不相关的(没有顺序可言),对于三元
?:
运算符来说,有特殊的排序规则“子表达式”用于覆盖像
a[++i][++i]
其中
a
是例如a
char**
:在这种情况下,两个相同的子表达式
++i
是不排序的,并且会产生副作用,修改相同的内存位置,从而导致未定义的行为。我认为该段落实际上比必要的更复杂,因为运算符的操作数也是子表达式因此,最后一部分就足够了。

让我给出一个答案,以便更清楚地回答这个问题。 首先,考虑下面的句子

除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是不排序的

这个句子可以分成两部分

1.除非另有说明,