Есть ли «очень плохо» , что может произойти , &&=
и ||=
были использованы в качестве синтаксического сахара для bool foo = foo && bar
и bool foo = foo || bar
?
126
Есть ли «очень плохо» , что может произойти , &&=
и ||=
были использованы в качестве синтаксического сахара для bool foo = foo && bar
и bool foo = foo || bar
?
x ||= y
примерно не эквивалентно C ++x = x ? x : y;
для любого типа? Другими словами, «установить в y, если еще не установлено». Это значительно более полезно, чем C или C ++x ||= y
, которые (запрещая перегрузку оператора) будут делать «установить x,(bool)y
если он еще не установлен». Я не хочу добавлять для этого еще одного оператора, это кажется немного слабым. Просто напишитеif (!x) x = (bool)y
. Но тогда я на самом деле не используюbool
достаточно переменных, чтобы требовать дополнительных операторов, которые действительно полезны только с этим одним типом.&&=
или||=
просто в том, что в C их нет. Я разумно уверен, что причина их отсутствия в C заключается в том, что функциональность не была сочтена достаточно полезной.bool foo = foo || bar;
вызовет неопределенное поведение, посколькуfoo
не инициализируется до оценкиfoo || bar
. Конечно, это должно быть что-то вроде,bool foo = …initialization…; …; foo = foo || bar;
и тогда вопрос остается актуальным.Ответы:
А
bool
может быть толькоtrue
илиfalse
в C ++. Таким образом, использование&=
и|=
относительно безопасно (хотя мне не особенно нравятся обозначения). Верно, они будут выполнять битовые операции, а не логические (и, следовательно, они не будут сокращать замыкание), но эти битовые операции следуют четко определенному отображению, которое фактически эквивалентно логическим операциям, если оба операнда имеют типbool
, 1Вопреки тому, что здесь говорили другие люди,
bool
в C ++ никогда не должно быть другого значения, например2
. При присвоении этого значения abool
оно будет преобразованоtrue
в соответствии со стандартом.Единственный способ получить недопустимое значение в a
bool
- использоватьreinterpret_cast
указатели:Но поскольку этот код в любом случае приводит к неопределенному поведению, мы можем спокойно игнорировать эту потенциальную проблему при согласовании кода C ++.
1 По общему признанию, это довольно серьезная оговорка, как показывает комментарий Энгью:
Причина в том, что
b & 2
целочисленное продвижение выполняется таким образом, что выражение затем эквивалентно выражениюstatic_cast<int>(b) & 2
, в результате0
чего получается выражение , которое затем преобразуется обратно вbool
. Так что это правда, что существование объектаoperator &&=
улучшит безопасность типов.источник
||
и&&
ярлык, то есть второй аргумент не является операндом, если первый операндtrue
(соответственноfalse
для&&
).|
,&
,|=
И&=
всегда оценивают оба операнда.&=
для левой стороны типаbool
, потому что это вполне возможно для правой руки , чтобы быть другого типа , чемbool
(например,islower
или другой функция STDLIB С , который возвращает отличное от нуля для истинного значения). Если бы у нас было гипотетическое&&=
, это, вероятно, заставило бы правую часть преобразоваться вbool
, чего&=
нет. Другими словами, вbool b = true; b &= 2;
результатеb == false
.&&
и&
имеют другую семантику:&&
не будет оценивать второй операнд, если первый операндfalse
. т.е. что-то вродебезопасно, но
нет, хотя оба операнда относятся к типу
bool
.То же самое относится и к
&=
и|=
:будет вести себя иначе, чем:
источник
Короткий ответ
Все операторы
+=
,-=
,*=
,/=
,&=
,|=
... являются арифметическими и обеспечивают такое же ожидание:Однако операторы
&&=
и||=
будут логичными, и эти операторы могут быть подвержены ошибкам, потому что многие разработчики ожидают, что ониfoo()
будут всегда вызваныx &&= foo()
.Неужели нам действительно нужно сделать C / C ++ еще более сложным, чтобы получить ярлык
x = x && foo()
?Неужели мы действительно хотим еще больше запутать загадочное утверждение
x = x && foo()
?Или мы хотим написать осмысленный код вроде
if (x) x = foo();
?Длинный ответ
Пример для
&&=
Если
&&=
оператор был доступен, то этот код:эквивалентно:
Этот первый код подвержен ошибкам, потому что многие разработчики думают, что
f2()
он всегда вызывается независимо отf1()
возвращаемого значения. Это похоже на запись,bool ok = f1() && f2();
гдеf2()
вызывается, только когдаf1()
возвращаетсяtrue
.f2()
чтобы его вызывали только приf1()
возвратеtrue
, следовательно, второй код выше менее подвержен ошибкам.f2()
чтобы его всегда вызывали)&=
достаточно:Пример для
&=
Более того, компилятору проще оптимизировать этот код выше, чем код ниже:
Сравните
&&
и&
Мы можем задаться вопросом, дают ли операторы
&&
и&
тот же результат при применении кbool
значениям?Давайте проверим, используя следующий код C ++:
Вывод:
Вывод
Поэтому YES мы можем заменить
&&
на&
дляbool
значений ;-)Так что лучше использовать
&=
вместо&&=
.Мы можем считать
&&=
бесполезным для логических значений.То же самое для
||=
Если разработчик хочет, чтобы
f2()
его вызывали только приf1()
возвратеfalse
, а не:Я советую следующую более понятную альтернативу:
или, если вы предпочитаете стиль единой линии :
источник
success = success && DoImportantStuff()
if(success) success = DoImportantStuff()
. Если бы операторsuccess &&= DoImportantStuff()
был разрешен, многие разработчики подумали бы, чтоDoImportantStuff()
он всегда вызывается независимо от значенияsuccess
. Надеюсь, это ответит на то, что вам интересно ... Я также улучшил многие части своего ответа. Скажите, пожалуйста, теперь мой ответ понятнее? (о цели вашего комментария) Ура, до встречи ;-)success &&= DoImportantStuff()
было разрешено, многие разработчики подумали бы, чтоDoImportantStuff()
оно всегда называется, независимо от ценности успеха». Вы можете сказать это об этомif (success && DoImportantStuff())
. Пока они помнят логику синтаксиса if, у них не должно возникнуть проблем&&=
.f1()
всегда дает оценку,ok &&= f(1)
но не будут считать, что она всегда дает оценкуok = ok && f(1)
. Мне это кажется столь же вероятным.v1 += e2
что это синтаксический сахарный эквивалентv1 = v1 + e1
переменной v1 и выражения e2. Просто сокращенное обозначение, вот и все.