c++11 评估顺序(未定义行为)

标签 c++ c++11 undefined-behavior

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 引入副作用,你只是在读取内存位置两次。

我相信这是解决问题的合理方法,它具有可读性并且不足为奇。另一种方法可以包括引入第二个变量,例如indexprev_index .给定这么小的代码片段,很难得出快速规则。

关于c++11 评估顺序(未定义行为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53065744/

相关文章:

c++ - 如何重载 static 和 dynamic_pointer_cast

c++ - 试图通过搜索注册表找到excel的路径

c++ - 如何正确增加 C++11 std::atomic?

c++ - 我可以使用 C++ 中的内置类型安全地新建 [],然后转换指针,然后删除 [] 吗?

c++ - 继承期间无法访问基址

c++ - 合并间隔/行 1034 : Char 9: runtime error: reference binding to null pointer of type 'std::vector<int, std::allocator<int>>'

c++ - 顺序异构函数执行器

c++ - 将整数紧密地打包在一个 vector 中 - 可以更快地完成吗?

rust - 如何正确使用 std::arch::_mm_loadu_si128/_mm_storeu_si128

C++ UBSAN 使用派生对象产生误报