【发布时间】:2011-04-20 15:32:05
【问题描述】:
很抱歉再次打开这个话题,但是考虑这个话题本身已经开始给我一个未定义的行为。想要进入定义明确的行为区域。
给定
int i = 0;
int v[10];
i = ++i; //Expr1
i = i++; //Expr2
++ ++i; //Expr3
i = v[i++]; //Expr4
我认为上述表达式(按此顺序)为
operator=(i, operator++(i)) ; //Expr1 equivalent
operator=(i, operator++(i, 0)) ; //Expr2 equivalent
operator++(operator++(i)) ; //Expr3 equivalent
operator=(i, operator[](operator++(i, 0)); //Expr4 equivalent
现在来到这里的行为是来自 C++ 0x 的重要引述。
$1.9/12-“表达式的求值 (或子表达式)一般 包括价值计算 (包括确定身份 用于左值评估的对象和 获取先前分配给的值 用于右值评估的对象)和 副作用的开始。”
$1.9/15-“如果对标量产生副作用 对象相对于 对相同的另一个副作用 标量对象或一个值 计算使用的值 相同的标量对象,行为是 未定义。”
[注:值计算和边 与不同的相关的影响 参数表达式是无序的。 ——尾注]
$3.9/9-“算术类型 (3.9.1), 枚举类型、指针类型、 指向成员类型的指针(3.9.2), std::nullptr_t 和 cv 限定 这些类型的版本(3.9.3)是 统称为标量类型。”
-
在 Expr1 中,表达式
i(第一个参数)的计算相对于表达式operator++(i)(有副作用)的计算是无序的。因此 Expr1 具有未定义的行为。
-
在 Expr2 中,表达式
i(第一个参数)的计算相对于表达式operator++(i, 0)(有副作用)的计算是无序的。因此 Expr2 具有未定义的行为。
-
在 Expr3 中,需要在调用外部
operator++之前完成对单独参数operator++(i)的评估。因此 Expr3 具有明确定义的行为。
-
在 Expr4 中,表达式
i(第一个参数)的计算相对于operator[](operator++(i, 0)(有副作用)的计算是无序的。因此 Expr4 具有未定义的行为。
这种理解正确吗?
附: OP中分析表达式的方法是不正确的。这是因为,正如@Potatoswatter 所指出的 - “第 13.6 条不适用。请参阅 13.6/1 中的免责声明,“这些候选函数参与 13.3.1.2 中所述的运算符重载解决过程,并且不用于其他目的。 " 它们只是虚拟声明;不存在与内置运算符相关的函数调用语义。"
【问题讨论】:
-
+!:好问题。我会留意答案。
-
@Chubsdad :我同意@James McNellis 在他的回答中所说的(他后来删除了)。所有 4 个表达式都在 C++0x [恕我直言] 中调用 UB。我认为你应该在 csc++ (comp.std.c++) 上问这个问题。
:) -
@Prasoon Saurav:为什么 Expr3 有未定义的行为?我认为这应该没问题。 gcc/comeau/llvm(demo) 也全部编译,没有任何警告。
-
那是因为与
++[inner] 和++[outer] 相关的副作用不是相对于彼此排序的(尽管值计算是排序的)。:) -
查看this。有人提到
Some more complicated cases are not diagnosed by -Wsequence-point option, and it may give an occasional false positive result,......
标签: c++ language-lawyer side-effects sequence-points