for(int i = 0; i < my_function(MY_CONSTANT); ++i){
//code using i
}
在此示例中,将my_function(MY_CONSTANT)
在每次迭代时进行评估,还是会自动存储?这是否取决于使用的优化标志?
for(int i = 0; i < my_function(MY_CONSTANT); ++i){
//code using i
}
在此示例中,将my_function(MY_CONSTANT)
在每次迭代时进行评估,还是会自动存储?这是否取决于使用的优化标志?
它必须像每次调用该函数一样工作。
但是,如果编译器能够证明每次的函数结果都是相同的,它就可以在“as if”规则下进行优化。
例如,这通常发生在.end()
对标准容器的调用中。
一般建议:当不确定是否对一段代码进行微优化时,
换句话说,根据代码的清晰程度来决定是否使用变量,而不是根据想象的性能。
每次迭代都会对其进行评估。您可以通过执行类似的操作来节省额外的计算时间
const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
//code using i
}
在您在此处的评论中概述的情况下,现代优化编译器as-if rule
可能能够优化函数调用。说符合标准的编译器只有模拟可观察的行为,我们可以通过 C++ 标准草案的程序执行部分看到这一点,它说:as-if rule
1.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
如果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.
}
所以你的问题的答案是......也许!