- 1
mExpanded = onExpandClick ? !mExpanded : mExpanded;
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+1009
mExpanded = onExpandClick ? !mExpanded : mExpanded;
им бы дать волю, они бы и циклы и сложения тернарным бы записывали
Ох, если бы так... ^^
http://ideone.com/nOjUL
Таже визуал студия за такое выдаст performance warning, затребовав вместо if(a^b) написать if((a^b)!=0)
Логические операции то не просто так придумали.
Через '!=' правильнее будет '!a != !b'. Это - логический xor. Но такой вариант, к сожалению, не создает точки следования между операндами (как это делают '&&' и '||).
Поэтому еще правильнее может быть '(!a && b) || (!b && a)'. Но этот вариант, к сожалению, страдает множественным вычислением операндов.
Что делать? А вот что: 'a ? !b : b'. Это - логический xor с точкой следования внутри и одноразовым вычислением операндов.
Не узнаете? Смотрим на код исходного автора и понимаем, что человек, вполне возможно, руководствовался вполне здравыми соображениями.
А чем это грозит? Порядок вычисления операндов не определён?
> 'a ? !b : b'. Это - логический xor с точкой следования внутри и одноразовым вычислением операндов.
b разве 2 раза не вычисляется?
Например, если кто-то определил макро 'XOR(a, b)' как '(!(a) != !(b))', то выражение 'XOR(i++, i)' будет порождать неопределенное поведение. А если макро определено как '((a) ? !(b) : (b))', то поведение определено, первый операнд гарантированно вычисляется до второго и их вычисление разделено точкой следования.
Одним из свойств оператора '?:' является то, что он вычисляет одну и только одну из своих условных подветок. Поэтому в данном определении операнд 'b' вычисляться будет строго один раз и строго после вычисления 'a'.
Что это? Бред или так и есть?
>Несколько присваиваний подряд
Интересный момент с таким кодом:
int a=1, b=2, c=3;
a=b=c=0;
Стандарт как-то очень нечетко описывает такую ситуацию. Он говорит, что операция должна происходить справа налево, но ничего не говорит дополнительно по поводу того, когда должен быть результат этой операции записан в переменную. Точек следования внутри выражения нет, что значит, что компилятор может теоретически творить здесь что угодно и не обязательно все переменные в итоге будут равны 0. Так что, опять же теоретически, здесь имеет место unspecified behavior.
звучит даже лучше, чем Майя Lucidfox
В реальности же 'a = b = 1' означает комбинацию 'b = 1' и 'a = (type_of_b) 1'. Т.е. оба присваивания в данном случае делаются независимо и не используют переменную 'b' в качестве "посредника". Никакой неопределенности тут нет.
Впрочем, я с вами соглашусь. Похоже на бред.
То есть точка следования между этими операторами пропадает после перегрузки этих операторов? То есть порядок вычисления аргументов этих операторов не определён? То есть уходит ленивость этого оператора? Что-за крестопроблемы... >_>
Кстати a , b активно используется в BOOST::ASSIGN. Все же перегрузка полезная.
Перегрузка операторов
a || b
a && b
нужна для создания своей обертки над bool или своих булевых алгебр, например BOOST::TRIBOOL. Тоже полезная перегрузка.
Сейчас же перегруженные || и && теряют свою семантику (превращаясь в | и &). Поэтому лучше их никогда-никогда не использовать.
Мне вот, к примеру пришлось недавно на жабе метод написать, который берёт список объектов, разбивает их на пары и попарно сравнивает (null-безопасным сравнением). Возвращает true, если объекты в парах равны. Проблемы начинаются, когда в метод нужно передавать объекты, являющиеся результатом вычислений. Если вычисления ресурсоёмкие (а такое бывает довольно часто), а сравнение прекратится до того момента, как дело дойдёт до результатов долгих вычислений, много тактов будет потрачено впустую.
в лиспе для оптимизации можно использовать простенький макрос, в хаскеле же практически любая чистая функция, реализующая этот функционал, будет работать правильно автоматически.
щас я себя минусану за глупость
вариант с джавой:
http://ideone.com/ETwvi
(обратим внимание: сообщения печатаются оба раза)
вариант с макросом на clojure:
http://ideone.com/K0quX
(а вот тут сообщения печатаются только второй раз, когда первые два объекта совпадают)
функция на Haskell выглядела бы так: Но вот запихнуть в неё выражения с побочными эффектами скорее всего не получится. Поэтому покажу вот на таком примере: Так вот, выражения someLongCalculation и anotherLongCalculation вычислены не будут.
Ну я так понял, что просто согласно принципу бритвы Оккама убрали одно понятие. Раньше было так:
«операция »," является точкой следования ->точка следования означает, что все побочные эффекты к моменту операции должны быть закончены->значит всё, что написано до запятой гарантировано выполнится до того, что написано после запятой"
стало:
«операция »," гарантирует, что всё, что написано до запятой гарантировано выполнится до того, что написано после запятой"
меньше понятий, меньше букв.
Что-то мне кажется, что про С++11 можно не думать еще года 2-3: стандарт-то приняли, а как с компиляторами дела обстоят?
Точки следования ещё не готовы.
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
j=j++ + a
n=(n=a)+b
По крайней мере только эти выражения фигурируют в примерах.
Сразу бы все проблемы ушли, если бы их (j++ и возможности присваивать результат операции = (присвоения) ) не было.
Проблемы с оптимизацией бы тоже ушли, которые есть из-за этих точек следования, из-за чего в C++11 снова перелопатили стандарт, пытаясь усилить оптимизацию, добавив в стандарт новые сущности и различные исключения из правил.
Вообще, от постинкремента больше проблем, чем пользы, впрочем как и от любых не чистых функций в правой части выражения.
Понятно, что порядок конструирования объектов не определён. но допустим уже успел сконструироваться первый объект, а второй после этого сконструированный объект в конструкторе кинет исключение. Понятно, что память занятая под второй сконструированный объект при этом сама освободится. А вот что будет с первым? Тоже освободится сама или утечёт?
Я при этом не говорю, что выражения вида 'i++ || i' надо использовать в коде, но тем не менее иногда что-то подобное бывает весьма полезно.
Няшненько... Как же С++/CLI этим раздражает...
и оба этих операнда друг на друга не влияют, так что как раз на откуп компилятору отдан порядок их вычисления, как и + и * и т.д.
а для || и && компилятор обязан слева направо вычислять