Логическое И, ИЛИ: оценка слева направо гарантирована? - PullRequest
26 голосов
/ 16 апреля 2011

Гарантируется ли логическая проверка слева направо (&& ||)?

Допустим, у меня есть это:

SDL_Event event;

if (SDL_PollEvent(&event)) {
    if (event.type == SDL_QUIT) {
            // do stuff
    }
}

Гарантируется ли это так же, как это?

SDL_Event event;

if (SDL_PollEvent(&event) && event.type == SDL_QUIT) {
    // do stuff
}

Это также может быть очень важно, скажем, у нас есть два требования, a и b. Требование a более вероятно не выполнится, чем b. Тогда эффективнее будет сказать if (a && b), чем if (b && a).

1 Ответ

43 голосов
/ 16 апреля 2011

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

Важное замечание : это действительно только для встроенных && и ||; если некоторые преступники их перегружают, они рассматриваются как «обычные» перегруженные бинарные операторы, поэтому в этом случае оба операнда всегда оцениваются и в неуказанном порядке, как обычно. По этой причине никогда не перегружайте их - это нарушает чрезвычайно важное предположение о потоке управления программой.


Соответствующие стандартные предложения

Встроенные && и || имеют гарантированное поведение при коротком замыкании

§5.14 ¶1

В отличие от &, && гарантирует оценку слева направо: второй операнд не оценивается, если первый операнд равен false.

§5.15 ¶1

В отличие от |, || гарантирует оценку слева направо; более того, второй операнд не оценивается, если первый операнд оценивается как true.

При перегрузке они ведут себя как «обычные» бинарные операторы (без короткого замыкания или гарантированного порядка вычисления)

§13,5 ¶9

Операторы, явно не упомянутые в подпунктах 13.5.3–13.5.7, действуют как обычные унарные и бинарные операторы, соблюдая правила 13.5.1 или 13.5.2.

и && и || явно не упомянуты в этих подпунктах, поэтому обычный §13.5.2 имеет место:

§13.5.2 *1

Бинарный оператор должен реализовываться либо нестатической функцией-членом (9.3) с одним параметром, либо функцией, не являющейся членом, с двумя параметрами. Таким образом, для любого бинарного оператора @ можно интерпретировать x@y как x.operator@(y) или operator@(x,y).

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

(все цитаты из стандарта C ++ 11)

...