*& ++我在C ++ 03中导致未定义的行为吗?

时间:2015-02-11 21:45:08

标签: c++ language-lawyer undefined-behavior c++03 sequence-points

another answer中有人说过,在C ++ 11之前,iint,然后使用表达式:

*&++i

导致未定义的行为。这是真的吗?

另一个答案是评论中有一点讨论,但似乎不能令人信服。

2 个答案:

答案 0 :(得分:7)

询问*&++i本身是否具有UB是没有意义的。引用不一定访问i的存储值(先前或新的),正如您可以通过将其用作引用的初始化表达式所看到的那样。只有涉及右值转换(在这种情况下使用)才有任何问题需要讨论。然后,由于我们可以使用++i的值,因此我们可以使用*&++i的值与++i完全相同的注意事项。

原始问题基本上与i = ++i有关,与i = *&++i相同。这是C ++ 03中未定义的行为,因为i在序列点之间被修改了两次,并且在C ++ 11中定义良好,因为赋值运算符的值在序列之后被排序计算左侧和右侧。

可能需要注意的是,C ++ 98和C ++ 03标准中的非规范性示例是不正确的,将某些正式未定义行为的情况描述为仅仅是未指定的行为。因此,意图一直没有完全清楚。一个好的经验法则是不要依赖语言的这些模糊的角落案例,以避免它们:为了理解代码,不应该成为一名语言律师......

答案 1 :(得分:0)

我认为这个问题只有在我们处理表达式时才有意义:

i = *&++i;

C ++ 03标准中的相关引用将是[expr] / 4:

  

除非另有说明,否则单个操作员的操作数和个体的子表达式的评估顺序   表达式以及副作用发生的顺序是未指定的。之间的   和下一个序列点标量对象的评估值最多只能修改一次   一个表达。此外,只能访问先前值以确定要存储的值。   对于完整的子表达式的每个允许排序,应满足本段的要求   表达;否则行为未定义。

i = ++i + 1; // the behavior is unspecified

我们可以比较i = *&++ii = ++i + 1的排序,以确定相同的规则会导致两者都未指定。它们都是以下形式的陈述:

i = f(++i);

对于任何函数f,左侧i的读数和右侧++i的副作用相对于每个函数都没有排序其他。因此,未定义的行为。