9
bool a1,a2,a3,a4,...;
a1=false;
while (a1 && a2 && a3 && a4 && ...) {...}

Будут ли в цикле проверяться условия a2,a3,a4,... или проверка завершится сразу после проверки a1?

assaqs
  • 93
  • 3

3 Answers3

19

Проверка завершится на первом операнде. Это гарантируется стандартом:

&& guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

в вольном переводе

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

Аналогично и для оператора || - если первый операнд - true, вычисление второго не производистя.

Это правило НЕ применяется для побитовых & и |.

Так же не выполняется для перегруженных операторов &&, || (в стандарте не нашел)

Yuriy Orlov
  • 1,996
  • 1
  • Если расположить условия в порядке уменьшения возможности быть false, я получу выигрыш? – assaqs Mar 10 '16 at 10:54
  • @assaqs, да, совершенно верно. К тому же если в условиях есть функции либо громоздкие выражения, они вызываться/вычислятся не будут. – Yuriy Orlov Mar 10 '16 at 10:56
  • Почему тогда http://ru.stackoverflow.com/questions/478096/Оптимизация-выбора ? – assaqs Mar 10 '16 at 10:58
  • там где то в стандарте была поправка, что если оператор operator&& перегружен, то будет вычислятся условие полностью. Но я пока не нашел ссылку на это. – KoVadim Mar 10 '16 at 11:07
  • @assaqs, м.б. не совсем то, что Вас сейчас интересует, но подобная техника иногда весьма удобна при работе с указателями if (p && *p ...) { ... } – avp Mar 10 '16 at 11:50
  • @assaqs, там совсем другая ситуация, там применяется оптимизация, в целом - в switch и цепочке if-else if - ... else нужно выбрать лишь одно из условий, и компилятор делает это способом, который он считает оптимальным, на результате работы это не отразится, только на производительности. – Yuriy Orlov Mar 10 '16 at 12:09
  • @KoVadim, нашёл только здесь - "built-in version of || and && use shortcut semantics. While the user defined ones do not use shortcut semantics." – Yuriy Orlov Mar 10 '16 at 12:30
  • @KoVadim если найдете - дайте знать. Но по идее, это вытекает из возможности задать любой возвращаемый тип для перегруженного оператора. Встроенный же оператор && принимает исключительно операнды, которые могут быть преобразованы в bool и возвращает bool же. Гарантия вычислений слева направо построена именно на этом. – αλεχολυτ Mar 10 '16 at 12:36
  • @YuriyOrlov таких фраз можно много по интернету найти. Интересно именно со сноской на пункт Стандарта. – αλεχολυτ Mar 10 '16 at 12:38
  • @alexolut, @KoVadim в стандарте не нашел, но если посудить - поведением оператора управляем мы, и в него должны передаваться два уже вычисленных объекта. И проверил - выполняется в msvc 12.0 – Yuriy Orlov Mar 10 '16 at 13:08
  • @YuriyOrlov управляем. Но до некоторой степени, например, нельзя изменить кол-во операндов, приоритеты операторов. Значение по умолчанию тоже задать нельзя. – αλεχολυτ Mar 10 '16 at 13:12
2

Если a1=false, то другие && нет смысла проверять, поэтому проверка остановится на a1.

Это очень просто проверить:

#include <iostream>

using namespace std;

bool a1() { cout << "a1\n"; return true; }

bool a2() { cout << "a2\n"; return true; }

bool a3() { cout << "a3\n"; return false; }

bool a4() { cout << "a4\n"; return true; }

int main(int argc, char *argv[]) { while (a1() && a2() && a3() && a4()) {

}

return 0;

}

Консоль:

a1
a2
a3
gil9red
  • 77,085
  • какой у вас компилятор? – assaqs Mar 10 '16 at 10:38
  • 2
    @assaqs Компилятор значения не имеет. Такое поведение определено стандартами. – Mike Mar 10 '16 at 10:39
  • @assaqs, mingw, и @Mike прав -- такое поведение одинаково для компиляторов – gil9red Mar 10 '16 at 10:51
  • Если расположить условия в порядке уменьшения возможности быть false, я получу выигрыш? – assaqs Mar 10 '16 at 10:55
  • да, вполне возможно. – KoVadim Mar 10 '16 at 11:08
0

В логических операций «И» и «ИЛИ» существует один подвох. Дело в том, что они участвуют в ленивых вычислениях. В отличие от побитовых операций. Если первый операнд в операции «И» имеет значение «ложь», а первый операнд операции «ИЛИ» — «истина», то дальнейшие вычисления не производятся. Потому что они бесполезны и уже не могут изменить результата. Но побитовым операциям для вычисления результата второй операнд нужен всегда.