Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

VS2013 C++11, && последовательность

318  
anly коренной житель26.08.16 16:33
anly
NEW 26.08.16 16:33 
Последний раз изменено 26.08.16 16:48 (anly)

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

Напр.

if (AA && BB){...} // BB не нужно вычислять если AA == false

Но сегодня неожиданно наткнулся что я не прав!

В оригинальном коде в качестве AA была функция возвращающая bool, а в качестве BB - просто сравнение.

Для своих дебаг-целей я заменил возвращаемое значение функции с bool на класс, который однако имеет операторы члены приведения к bool и &&.

В этом случае оказалось что BB вычисляется первым! А в этом старом коде последовательность важна.


Разве последовательность не стандартизирована?

Проклят нарушающий межи ближнего своего (Втор.27:17)
#1 
anly коренной житель26.08.16 16:58
anly
NEW 26.08.16 16:58 
в ответ anly 26.08.16 16:33, Последний раз изменено 26.08.16 17:03 (anly)

если поточнее то подобный код:


bool GetPtr(void **p)

{

*p = (void*)1;

return true;

}


void main()

{

void* p = NULL;

if (GetPtr(&p) && p != NULL)

{

....сюда не войдёт если GetPtr возвращает класс, т.к. в этом случае p != NULL будет вычислено раньше вызова GetPtr.

однако войдёт если GetPtr возвращает bool.

}

}

Проклят нарушающий межи ближнего своего (Втор.27:17)
#2 
Murr патриот26.08.16 17:03
Murr
NEW 26.08.16 17:03 
в ответ anly 26.08.16 16:58

if(p = GetPtr()) ? не ==, а = ?

if((p = GetPtr()) != NULL) ?

#3 
anly коренной житель26.08.16 17:06
anly
NEW 26.08.16 17:06 
в ответ Murr 26.08.16 17:03, Последний раз изменено 26.08.16 17:06 (anly)

код уже написан и встречается в сотнях мест (больше 20 лет программе). Так что менять столько мест не желательно.

Проклят нарушающий межи ближнего своего (Втор.27:17)
#4 
Murr патриот26.08.16 17:14
Murr
NEW 26.08.16 17:14 
в ответ anly 26.08.16 17:06

Search & Replace = 10 минут...

#5 
pavel-hh свой человек26.08.16 17:23
pavel-hh
NEW 26.08.16 17:23 
в ответ anly 26.08.16 16:33, Последний раз изменено 26.08.16 17:33 (pavel-hh)

да вроде ничего не менялось как был && short-circuit evaluation так и осталось.

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

EDIT: о, вот что еще, это прям ваш случай!

http://en.cppreference.com/w/cpp/language/oper...

Restrictions

  • The operators :: (scope resolution), . (member access), .* (member access through pointer to member), and ?: (ternary conditional) cannot be overloaded.
  • New operators such as **, <>, or &| cannot be created.
  • The overloads of operators && and || lose short-circuit evaluation.
  • The overload of operator -> must either return a raw pointer or return an object (by reference or by value), for which operator -> is in turn overloaded.
  • It is not possible to change the precedence, grouping, or number of operands of operators.
Linux is like a Wigwam. No Windows! No Gates! And Apache inside.
#6 
anly коренной житель26.08.16 17:59
anly
NEW 26.08.16 17:59 
в ответ Murr 26.08.16 17:14, Последний раз изменено 26.08.16 18:00 (anly)
Search & Replace = 10 минут...

это только со стороны кажется что так просто. Поиск конечно сработает, но только самой функции, но Замена - придётся ручками. Т.к. функция имеет несколько параметров и они в каждом случае имеют другие имена.

Проклят нарушающий межи ближнего своего (Втор.27:17)
#7 
anly коренной житель26.08.16 18:02
anly
NEW 26.08.16 18:02 
в ответ pavel-hh 26.08.16 17:23
вы никаких многопоточных прибамбасов не подключили?
нет. Я даже протестировал приведённый в #2 код в простейшем консольном приложении - таже беда.
Проклят нарушающий межи ближнего своего (Втор.27:17)
#8 
anly коренной житель26.08.16 18:04
anly
26.08.16 18:04 
в ответ pavel-hh 26.08.16 17:23
The overloads of operators && and || lose short-circuit evaluation.
значит они сознательно напортачили!
Проклят нарушающий межи ближнего своего (Втор.27:17)
#9 
Krist5 прохожий26.08.16 18:06
NEW 26.08.16 18:06 
в ответ anly 26.08.16 16:33, Последний раз изменено 26.08.16 18:09 (Krist5)

1. Если в выражении AA && BB AA вернуло false, то по умолчанию BB вычислено не будет, хотя как указал pavel-hh это можно переопределить, (если очень хочется) написав свой собственный operator&&.

2. А как Вы определили operator&& в Вашем классе?

3. Лучше всего поместите целую законченную программу, которая компилируется. Иначе всё слишком абстрактно.


PS Сомневаюсь, что кто-то сознательно напортачил.

#10 
pavel-hh свой человек26.08.16 18:12
pavel-hh
NEW 26.08.16 18:12 
в ответ Krist5 26.08.16 18:06
PS Сомневаюсь, что кто-то сознательно напортачил.

т.е. сомневаетесь? они даже документацию написали:-)

Linux is like a Wigwam. No Windows! No Gates! And Apache inside.
#11 
anly коренной житель26.08.16 18:17
anly
NEW 26.08.16 18:17 
в ответ Murr 26.08.16 17:14, Последний раз изменено 26.08.16 18:26 (anly)

Вот погладел сколько раз встречается: почти 2500 раз.

так что ручками если вмешиваться - на долго.

Оставлю так.


Просто я хотел возвращение класса оставить в Дебаг версии. Но т.к. поведение меняется, то нельзя даже для Дебага.

Но свою службу класс отслужил: при компилировании он показал (выдал ошибки) все места где возвращаемый bool прислваивался или сравнивался с HRESULT.

На одну такую лажу я наткнулся и решил проверить всю программу. Нашел много тупого кода типа if (FAILED(GetPtr())) тоже и с SUCCEEDED. Который ввиду булевского возврата означает if(false) или if(true).


эти макросы такие, если кто не знаком:

#define FAILED(h) ((h) < 0)

#define SUCCEDED(h) ((h) >= 0)

Проклят нарушающий межи ближнего своего (Втор.27:17)
#12 
pavel-hh свой человек26.08.16 18:28
pavel-hh
NEW 26.08.16 18:28 
в ответ anly 26.08.16 18:17
Вот погладел сколько раз встречается: почти 2500 раз.так что ручками если вмешиваться - на долго.Оставлю так.

под линуксом или в cygwin можно было бы и 5000 замен с разными параметрами повестиспок

Linux is like a Wigwam. No Windows! No Gates! And Apache inside.
#13 
anly коренной житель26.08.16 18:41
anly
NEW 26.08.16 18:41 
в ответ pavel-hh 26.08.16 18:28, Последний раз изменено 26.08.16 20:07 (anly)

а что там за сервис такой?


я сам подумывал над использованием регулярных выражений, но - не силён в них, особенно в Замене (поиском пользуюсь).

Кто знает, можно ли там одним кликом найти и заменить типа того:

AAA xxx BBB ---> CCC xxx DDD

где xxx - постоянно разное, а AAA.BBB,CCC,DDD всегда одинаковы.

?


EDIT:

понял сам - ищем AAA(.*)BBB, заменяем на CCC$1DDD

Проклят нарушающий межи ближнего своего (Втор.27:17)
#14 
MrSanders старожил26.08.16 20:50
NEW 26.08.16 20:50 
в ответ anly 26.08.16 18:41
AAA(.*)BBB, заменяем на CCC$1DDD

Аккуратнее. Простая * обычно "жадный" квантор. Т.е. заберет максимум того, что сможет.

Из AAAxxxxxxBBByyyyyBBB заберет xxxxxxBBByyyyy

Если у вас такого не встречается, тогда не страшно. А так - меняйте на "не жадный". Как оно в sed-е я уже и не помню. Что-то вроде *? вместо *

#15 
pavel-hh свой человек26.08.16 21:12
pavel-hh
NEW 26.08.16 21:12 
в ответ MrSanders 26.08.16 20:50

sed вроде non-greedy модус не поддерживает, поэтому лучше perl в этом случае

Linux is like a Wigwam. No Windows! No Gates! And Apache inside.
#16 
anly коренной житель26.08.16 22:28
anly
NEW 26.08.16 22:28 
в ответ MrSanders 26.08.16 20:50

спасибо, учту

Проклят нарушающий межи ближнего своего (Втор.27:17)
#17 
vlad_s_69 свой человек31.08.16 13:26
NEW 31.08.16 13:26 
в ответ anly 26.08.16 16:33

BB не надо вычислять если АА false

скорее всего сеттинги оптимизации слетели

#18 
pavel-hh свой человек31.08.16 13:37
pavel-hh
NEW 31.08.16 13:37 
в ответ vlad_s_69 31.08.16 13:26

вы бы всю ветку прочитали, а потом писали бы. вроде уже разобрались в чем проблема.

Linux is like a Wigwam. No Windows! No Gates! And Apache inside.
#19