在什么时候C ++优化中的代码重新排序停止了?

时间:2013-06-26 19:36:08

标签: c++ c++11

关于优化代码中的代码执行保证,我一直在阅读关于SO的一些问题,所以我正在尝试编译一个原因列表,说明允许/阻止编译器重新排序代码序列的原因。

我已经开始回答一般情况但是我没有添加标准的引用(这取自我的经验)。如果有任何遗忘或扩展/纠正在那里的点,我会要求你添加答案。

此外,如果代码块不需要重新排序,有人可以验证我。即。

void fn()
{
  { /* code block 1 */ ... }
  { /* code block 2 */ ... }
}

code block 1中的代码是否可以混合或者之前 code block 2执行?

2 个答案:

答案 0 :(得分:5)

该标准为编译器提供了很多余地,可以重新排序代码并执行各种其他优化。对优化器唯一真正的约束是执行代码的可观察结果应该“好像”代码是按程序员编写的顺序执行的。只要遵循“似乎”规则,编译器/链接器/ CPU /内存子系统就可以自由地重新排序他们喜欢的任何内容。变量上的volatile修饰符限制了重新排序(或删除)对该变量的读取和写入的机会,因为它告诉编译器它不能对从一个读取或写入到另一个的变量的状态做出任何假设,但它通常不会影响对同一段代码中其他非易失性变量的读写。

C ++ 11标准添加了额外的语言,明确说明在多线程世界中存在哪些保证,其中事情要复杂得多。在这里,该标准保证了数据竞争免费程序的顺序一致性。如果程序员使用正确的同步并且不写任何数据争用,这实际上是'似乎'规则。如果您的代码有数据竞争,那么您可能能够观察到如果代码是按照您执行多个同时执行的线程时编写的顺序执行的,则无法实现的结果。 C ++ 11原子和内存屏障提供了向编译器表达额外约束的方法,可以在存在多个同时执行的线程的情况下安全地执行哪种重新排序。

答案 1 :(得分:-2)

如果出现以下情况,可能会发生相对于其他代码的代码重新排序:

  1. 执行的代码与其周围的代码序列正交(不依赖于以前的代码或依赖于未来的代码)。
  2. 如果符合以下条件,则无法对代码进行重新排序:

    1. 编译器无法获得有关代码修改内容的信息。即调用声明可用但不是定义的函数。
    2. 访问volatile变量要求不得对w.r.t重新排序。彼此(但也有额外的约束,他们的值不是由编译器缓存,但可能由硬件缓存)。