C ++评估顺序,排序顺序以及编译器重新排序?

时间:2018-11-09 10:05:08

标签: c++ c++11

我已经读过Order of evaluation,但我不太理解。该顺序是指运行时的执行顺序还是源代码中的逻辑顺序?

让我们看一下下面的代码段:

void f()
{
   int a = 10; // A
   int b = 20; // B
   //...
}

这是否意味着在表达式A之前对表达式B进行了排序?

并且C ++编译器是否可以按如下所示重新排序代码?

void f()
{
   int b = 20; // B
   int a = 10; // A
    //...
}

如果编译器确实按上述方式对代码进行了重新排序,那么我们应该说表达式B是在A之前排序的吗?

1 个答案:

答案 0 :(得分:4)

通常,只要结果与编译代码完全一样,编译器就可以做任何事情

实际上,您的典型C / C ++编译器已启用任何合理的优化标志,并具有以下功能:

void f (void) {
  int a = 20;
  int b = 10;
}

将其简单地编译为:

f:
  ret

换句话说,它将把它当作一个空函数。原因是该功能没有任何作用。这些变量已分配给它们,但它们的值从未使用过(从技术上讲,它们是死存储区),因此编译器可以忽略它们。

现在,让我们看一个更实际的例子:

void foo (int num, int * num2, int * num3) {
  *num2 = num * 2;
  *num3 = num * 3;
}

编译器可以对这些语句重新排序吗?答案是肯定的。原因是num2num3可能指向相同的地址(换句话说,您可以调用foo(3, &bar, &bar)之类的函数),因此写入的顺序很重要。另一方面,仅在C语言中(而不在C ++语言中),我们可以这样写:

void foo (int num, int * restrict num2, int * restrict num3) {
  *num2 = num * 2;
  *num3 = num * 3;
}

在那种情况下,restrict关键字告诉编译器指针必须指向不同的地址,因此可以对语句进行重新排序,因为无论执行顺序如何,结果都是相同的。