2
for(int i = 0; i < my_function(MY_CONSTANT); ++i){
    //code using i
}

在此示例中,将my_function(MY_CONSTANT)在每次迭代时进行评估,还是会自动存储?这是否取决于使用的优化标志?

4

4 回答 4

10

它必须每次调用该函数一样工作。

但是,如果编译器能够证明每次的函数结果都是相同的,它就可以在“as if”规则下进行优化。

例如,这通常发生在.end()对标准容器的调用中。


一般建议:当不确定是否对一段代码进行微优化时,

  1. 不要这样做。
  2. 如果您仍在考虑这样做,请测量
  3. 好吧,还有第三点,但我忘记了,也许是,还在等。

换句话说,根据代码的清晰程度来决定是否使用变量,而不是根据想象的性能。

于 2014-10-14T14:12:37.897 回答
3

每次迭代都会对其进行评估。您可以通过执行类似的操作来节省额外的计算时间

const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
    //code using i
}
于 2014-10-14T14:11:39.747 回答
2

在您在此处的评论中概述的情况下,现代优化编译器as-if rule可能能够优化函数调用。说符合标准的编译器只有模拟可观察的行为,我们可以通过 C++ 标准草案的程序执行部分看到这一点,它as-if rule1.9

[...]相反,需要符合要求的实现来模拟(仅)抽象机器的可观察行为,如下所述。 5

因此,如果您使用的是常量表达式并且my_function没有可观察到的副作用,则可以对其进行优化。我们可以进行一个简单的测试(在 Godbolt 上查看):

#include <stdio.h>

#define blah 10

int func( int x )
{
  return x + 20 ;
}

void withConstant( int y )
{
  for(int i = 0; i < func(blah); i++)
  {
    printf("%d ", i ) ;
  }
}

void withoutConstant(int y)
{
  for(int i = 0; i < func(i+y); i++)
  {
    printf("%d ", i ) ;
  }
}

在这种情况下,withConstant我们可以看到它优化了计算:

cmpl    $30, %ebx   #, i

甚至在withoutConstant它内联计算而不是执行函数调用的情况下:

leal    0(%rbp,%rbx), %eax  #, D.2605
于 2014-10-14T15:59:41.657 回答
1

如果my_function声明为 constexpr 并且参数实际上是一个常量,则在编译时计算该值,从而满足“as-if”和“sequential-consistency with no data-race”规则。

constexpr my_function(const int c);

如果您的函数有副作用,它将阻止编译器将其移出,for-loop因为它不会满足“as-if”规则,除非编译器可以推理出它的出路。

编译器可能会 inline my_function,对其进行 reduce ,就好像它是循环的一部分一样,并且不断减少会发现它实际上只是一个常量,事实上删除了调用并将其替换为常量。

int my_function(const int c) {
    return 17+c; // inline and constant reduced to the value.
}

所以你的问题的答案是......也许!

于 2014-10-14T15:05:17.463 回答