for(int i = 0; i < my_function(MY_CONSTANT); ++i){
//code using i
}
В этом примере будет my_function(MY_CONSTANT)
будет оцениваться на каждой итерации или будет сохраняться автоматически? Зависит ли это от используемых флагов оптимизации?
Это должно работать как будто функция вызывается каждый раз.
Однако, если компилятор может доказать, что результат функции будет одинаковым каждый раз, он может оптимизироваться в соответствии с правилом «как будто».
Например. это обычно происходит с звонками .end()
для стандартных контейнеров.
Общий совет: если вы сомневаетесь, нужно ли микрооптимизировать фрагмент кода,
Другими словами, решите, использовать ли переменную, основываясь на том, насколько ясен код, а не на воображаемой производительности.
Будет оцениваться каждая итерация. Вы можете сэкономить дополнительное время вычислений, выполнив что-то вроде
const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
//code using i
}
Современный оптимизирующий компилятор под as-if rule
может быть в состоянии оптимизировать вызов функции в случае, который вы указали в своем комментарий здесь. as-if rule
говорит, что соответствующий компилятор только эмулирует наблюдаемое поведение, мы можем убедиться в этом, перейдя к черновому стандартному разделу C ++ 1.9
Выполнение программы который говорит:
[…] Скорее соответствующие реализации должны эмулировать (только)
наблюдаемое поведение абстрактной машины, как объяснено ниже.
Так что если вы используете постоянное выражение а также 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, а аргумент действительно является константой, значение вычисляется во время компиляции и, таким образом, соответствует правилам «как будто» и «последовательная согласованность без гонки данных».
constexpr my_function(const int c);
Если у вашей функции есть побочные эффекты, это не позволит компилятору переместить ее из for-loop
так как он не будет выполнять правило «как будто», если только компилятор не сможет найти выход из него.
Компилятор может быть встроенным my_function
уменьшите его, как если бы он был частью цикла, и с постоянным сокращением выясните, что это действительно только константа, де-факто удаляющая вызов и заменяющая его константой.
int my_function(const int c) {
return 17+c; // inline and constant reduced to the value.
}
Таким образом, ответ на ваш вопрос … возможно!