Будет ли компилятор VS2008 c ++ оптимизировать следующий оператор if? - PullRequest
0 голосов
/ 16 декабря 2009
if (false == x) { ...}

вместо:

if (!x) { ... }

и

if (false == f1()) { ...}

вместо:

if (!f1()) { ... }

Я думаю, что версия if (false == ... более читабельна.

Вот почему я не люблю! X:

if (25 == a->function1(12345, 6789) &&
    45 == b->function1(12345, 6789) &&
    !c->someOtherFunction(123)) { ... }

Лучше выглядит следующее:

if (25 == a->function1(12345, 6789) &&
    45 == b->function1(12345, 6789) &&
    false == c->someOtherFunction(123)) { ... }

Ответы [ 6 ]

7 голосов
/ 16 декабря 2009

Я думаю, что версия if (false == ... более читабельна. Вы согласны или можете предложить другой трюк?

Вы делаете это неправильно.

false == x возвращает логическое значение, которое, очевидно, должно сравниваться с true!

if (true == (false == x)) { ...} будет лучше. Но это снова возвращает bool, поэтому, чтобы быть в безопасности и сделать ваш код более читабельным, нам лучше сделать это:

if (true == (true == (false == x))) { ...}. И так далее. Как только вы начнете сравнивать логические значения с логическими, где вы остановитесь? Результат всегда будет другим логическим значением, и чтобы быть последовательным, вы должны сравнить это с логическим значением.

Или вы можете научиться понимать язык, на котором вы работаете, и использовать if (!x) { ...}, который выражает именно то, что вы хотели.

Что вы на самом деле считаете более читабельным?

  • if (false == x) { ...} переводится как «Если это правда, что false равно x».
  • if (!x) { ...} переводится как «если x не соответствует действительности».

Можете ли вы честно, серьезно, действительно сказать, что первая форма "более читабельна"? Вы когда-нибудь сказали бы это в предложении? «Если это правда, что ложь равна х»?

Он не более читабелен, он просто кричит любому программисту, читающему ваш код: «Я не понимаю, являются ли операторы или логические значения».

7 голосов
/ 16 декабря 2009

Лично я нахожу форму if (!x) { ... } наиболее читаемой, но в настоящее время все они приводят к одному и тому же коду.

РЕДАКТИРОВАТЬ: В вашем примере, я бы сделал следующее:

if (  a->function1(12345, 6789) == 25 &&
      b->function1(12345, 6789) == 45 &&
    !(c->someOtherFunction(123))) { ... }

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

4 голосов
/ 16 декабря 2009

C ++ резервирует следующие ключевые слова слева в качестве альтернативы операторам справа:

and  and_eq  bitand    &&  &=  &
or   or_eq   bitor     ||  |=  |
     xor_eq  xor           ^=  ^
not  not_eq  compl     !   !=  ~

Если вы беспокоитесь о потере !, not выделяется больше.

if (    a->function1(12345, 6789) == 25 and
        b->function1(12345, 6789) == 45 and
        not c->someOtherFunction(123)) {
    ...
}
3 голосов
/ 16 декабря 2009

Хороший компилятор должен генерировать одинаковый код для обоих блоков кода.

Однако, вместо того, чтобы беспокоиться о false == f1() против !f1(), вы должны быть более обеспокоены оценкой короткого замыкания в этом примере:

if (25 == a->function1(12345, 6789) &&
    45 == b->function1(12345, 6789) &&
    !c->someOtherFunction(123)) { ... }

Некоторые компиляторы будут генерировать код, который будет пропускать выполнение b->function1() и c->someOtherFunction(), если вызов a->function1() оценивается чем-то отличным от 25 - причина в том, что компилятор уже знает результат всего if () оператор в этой точке, чтобы он мог прыгнуть в нужном месте.

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

2 голосов
/ 16 декабря 2009

Это случай преждевременной оптимизации ( Когда оптимизация преждевременная? ). Но компилятор сгенерирует тот же код (режим отладки MSVC 2008):

if (!bVal)
    bVal = true;

if (bVal == false)
    bVal = true;

//translates to

; 70   :         if (!bVal)

cmp BYTE PTR $T5793[ebp], 0
jne SHORT $LN9@wmain
push    OFFSET $LN10@wmain
call    __RTC_UninitUse
add esp, 4
$LN9@wmain:
movzx   eax, BYTE PTR _bVal$[ebp]
test    eax, eax
jne SHORT $LN2@wmain

; 71   :             bVal = true;

mov BYTE PTR $T5793[ebp], 1
mov BYTE PTR _bVal$[ebp], 1
$LN2@wmain:

; 72   :         
; 73   :         if (bVal == false)

cmp BYTE PTR $T5793[ebp], 0
jne SHORT $LN11@wmain
push    OFFSET $LN10@wmain
call    __RTC_UninitUse
add esp, 4
$LN11@wmain:
movzx   eax, BYTE PTR _bVal$[ebp]
test    eax, eax
jne SHORT $LN1@wmain

; 74   :             bVal = true;

mov BYTE PTR $T5793[ebp], 1
mov BYTE PTR _bVal$[ebp], 1
1 голос
/ 16 декабря 2009

Профилировали ли вы и находили ли вы оценку состояния горячей точки? Если нет, то делайте все, что требует ваш стандарт кодирования.

В любом случае оба должны компилироваться в один и тот же код. Вы можете проверить, проверив код сборки, сгенерированный компилятором для обоих случаев.

...