vec[ival++] <= vec[ival]
此表达式具有未定义的行为,因为运算符 (<=) 操作数的求值顺序未定义。
我们如何重写该表达式以避免未定义的行为? 我找到了一个似乎有效的答案:
vec[ival] <= vec[ival + 1]
如果那是避免未定义行为的正确方法,为什么用这种方式重写它可以避免未定义行为?
添加任何关于如何修复该表达式的引用会很棒。
最佳答案
是的,您的第一个示例具有未定义的行为,因为我们对内存位置进行了无序的修改和访问,这是未定义的行为。这包含在 C++ 标准草案 [intro.execution]p10 中。 (强调我的):
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. — end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a memory location ([intro.memory]) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent ([intro.multithread]), the behavior is undefined. [ Note: The next subclause imposes similar, but more complex restrictions on potentially concurrent computations. — end note ] [ Example:
void g(int i) { i = 7, i++, i++; // i becomes 9 i = i++ + 1; // the value of i is incremented i = i++ + i; // the behavior is undefined i = i + 1; // the value of i is incremented }
— end example ]
如果我们查看涵盖 <=
的关系运算符部分[expr.rel]它没有指定评估顺序,所以我们被 intro.exection
涵盖了因此我们有未定义的行为。
具有未指定的评估顺序对于未定义的行为是不够的,如 Order of evaluation of assignment statement in C++ 中的示例演示。
您的第二个示例避免了未定义的行为,因为您没有向 ival
引入副作用,你只是在读取内存位置两次。
我相信这是解决问题的合理方法,它具有可读性并且不足为奇。另一种方法可以包括引入第二个变量,例如index
和 prev_index
.给定这么小的代码片段,很难得出快速规则。
关于c++11 评估顺序(未定义行为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53065744/