Будет ли следующий код оптимизирован для одного вызова функции?

У меня очень мало (читай нет) опыта работы с компилятором, и мне было интересно, будет ли следующий фрагмент кода автоматически оптимизирован относительно недавним (VS2008 + / GCC 4.3+) компилятором:

Object objectPtr = getPtrSomehow();

if (objectPtr->getValue() == something1)       // call 1
dosomething1;
else if (objectPtr->getValue() == something2)  // call N (there are a few more)
dosomething2;

return;

где getValue () просто возвращает переменную-член, которая является одной из перечисления. (Звонок не имеет заметного эффекта)

Мой стиль кодирования будет заключаться в том, чтобы сделать один вызов перед «switch» и сохранить значение, чтобы сравнить его с каждым из someX, но мне было интересно, было ли это спорным вопросом с современными компиляторами.

Я также был не уверен, что гуглить, чтобы найти ответ на это сам.

Спасибо,

Аляска

3

Решение

Если компилятор не может проверить определение getValue() в то время как он компилирует этот фрагмент кода, он не может исключить второй вызов, потому что он не знает, имеет ли этот вызов наблюдаемые эффекты и возвращает ли он то же значение во второй раз.

Даже если он видит определение, это наверное (это мое дикое предположение о том, что у меня есть несколько взглядов на внутренности некоторых компиляторов), не сделаю все возможное, чтобы проверить это. Единственный шанс, которым вы стоите, — это тривиальная реализация а также встроенный дважды, и затем пойман общим устранением подвыражения. РЕДАКТИРОВАТЬ: Поскольку определение находится в заголовке и довольно мало, вполне вероятно, что это (встроенный и последующий CSE) произойдет. Тем не менее, если вы хотите быть уверены, проверьте вывод g++ -O2 -S или эквивалент вашего компилятора.

Итак, в заключение, вы не должны ожидать оптимизация произойдет. Тогда снова, getValue это, вероятно, довольно дешево, так что вряд ли стоит ручных оптимизаций. Какая дополнительная линия по сравнению с парой машинных циклов? Не очень, в большинстве случаев. Если вы пишете код там, где его много, вам не нужно спрашивать, а просто проверять его (дизассемблирование / профилирование).

3

Другие решения

Это не спорный, особенно если метод является изменяемым.

Если getValue не объявлено constвызов не может быть оптимизирован, поскольку последующие вызовы могут возвращать разные значения.

Если это объявлено const, это проще, но также нетривиально для компилятора, чтобы оптимизировать вызов. Требуется доступ к реализации, чтобы убедиться, что вызов не имеет побочных эффектов. Существует также вероятность того, что он возвращает другое значение, даже если отмечен const (изменяет и возвращает глобальный).

4

Как отмечали другие ответы, компилятор, как правило, не может устранить второй вызов, поскольку могут быть побочные эффекты.

Однако у некоторых компиляторов есть способ сообщить компилятору, что функция не имеет побочных эффектов и что эта оптимизация разрешена. В GCC функция может быть объявлена чистый. Например:

int square(int) __attribute__((pure));

говорит, что функция не имеет «никаких эффектов, кроме как для возврата значения, и возвращаемое значение зависит только от параметров и / или глобальных переменных».

2

Вы написали:

Мой стиль кодирования — сделать один вызов перед «переключателем» и сохранить значение для сравнения.
это против каждого из чего-то X, но мне было интересно, если это был спорный вопрос
с сегодняшними компиляторами.

Да, это спорный вопрос. То, что делает компилятор, это бизнес. Ваши руки будут полны попыток написать обслуживаемый код, не пытаясь управлять программным обеспечением на микроуровне, которое намного лучше справляется со своей работой, чем кто-либо из нас когда-либо надеялся.

Сосредоточьтесь на написании поддерживаемого кода и доверьте компилятору свою задачу. Если позже вы обнаружите, что ваш код слишком медленный, вы можете беспокоиться об оптимизации.

Помните пословицу:

Преждевременная оптимизация — корень всего зла.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector