Existe uma "coisa muito ruim" que pode acontecer &&=
e ||=
foi usada como açúcar sintático para bool foo = foo && bar
e bool foo = foo || bar
?
c++
boolean-operations
Kache
fonte
fonte
x ||= y
aproximadamente equivalente a C ++x = x ? x : y;
para qualquer tipo? Em outras palavras, "defina como y se ainda não estiver definido". Isso é consideravelmente mais útil do que C ou C ++x ||= y
, que (exceto a sobrecarga do operador) faria "definir x como a(bool)y
menos que já esteja definido". Não estou ansioso para adicionar outro operador para isso, parece um pouco fraco. Apenas escrevaif (!x) x = (bool)y
. Mas, na verdade, não usobool
variáveis suficientes para desejar operadores extras que sejam realmente úteis apenas com esse tipo.&&=
ou||=
é simplesmente porque o C não os possui. Tenho certeza de que a razão pela qual C não os possui é que a funcionalidade não foi considerada benéfica o suficiente.bool foo = foo || bar;
invocaria um comportamento indefinido porquefoo
não é inicializado antes da avaliação defoo || bar
. Obviamente, isso pretende ser algo parecidobool foo = …initialization…; …; foo = foo || bar;
e a pergunta permanece válida.Respostas:
A
bool
pode ser apenastrue
oufalse
em C ++. Como tal, usar&=
e|=
é relativamente seguro (mesmo que eu não goste da notação). É verdade que eles executarão operações de bits em vez de operações lógicas (e, portanto, não entrarão em curto-circuito), mas essas operações de bits seguem um mapeamento bem definido, que é efetivamente equivalente às operações lógicas, desde que os dois operandos sejam do tipobool
. 1Ao contrário do que outras pessoas disseram aqui, a
bool
em C ++ nunca deve ter um valor diferente, como2
. Ao atribuir esse valor abool
, ele será convertido detrue
acordo com o padrão.A única maneira de obter um valor inválido em a
bool
é usandoreinterpret_cast
ponteiros:Porém, como esse código resulta em um comportamento indefinido, podemos ignorar com segurança esse possível problema em conformidade com o código C ++.
1 É certo que essa é uma advertência bastante grande, como o comentário de Angew ilustra:
O motivo é que
b & 2
realiza a promoção inteira, de forma que a expressão seja equivalente astatic_cast<int>(b) & 2
, o que resulta em0
, e depois é convertida novamente em abool
. Portanto, é verdade que a existência de umoperator &&=
melhoraria a segurança do tipo.fonte
||
e&&
atalho, ou seja, o segundo argumento não é operando se o primeiro operando fortrue
(resp.false
for&&
).|
,&
,|=
E&=
sempre avaliar ambos os operandos.&=
por um lado esquerdo do tipobool
, porque é perfeitamente possível para o lado direito de ser do tipo que não sejabool
(comoislower
ou outra função stdlib C que retorna diferente de zero para valor verdadeiro). Se tivéssemos o hipotético&&=
, provavelmente forçaria o lado direito a se converterbool
, o que&=
não acontece. Em outras palavras,bool b = true; b &= 2;
resulta emb == false
.&&
e&
tem semântica diferente:&&
não avaliará o segundo operando se o primeiro operando forfalse
. ou seja, algo comoestá seguro, mas
não é, embora ambos os operandos sejam do tipo
bool
.O mesmo vale para
&=
e|=
:se comportará de maneira diferente de:
fonte
Resposta curta
Todos os operadores
+=
,-=
,*=
,/=
,&=
,|=
... são aritmética e fornecer mesma expectativa:No entanto, os operadores
&&=
e||=
seriam lógicos, e esses operadores podem estar sujeitos a erros, porque muitos desenvolvedores esperam quefoo()
sejam sempre chamadosx &&= foo()
.Nós realmente precisamos tornar o C / C ++ ainda mais complexo para obter um atalho
x = x && foo()
?Realmente queremos ofuscar mais a afirmação enigmática
x = x && foo()
?Ou queremos escrever um código significativo como
if (x) x = foo();
?Resposta longa
Exemplo para
&&=
Se o
&&=
operador estivesse disponível, este código:é equivalente a:
Esse primeiro código é suscetível a erros porque muitos desenvolvedores pensam que
f2()
sempre é chamado de qualquerf1()
valor retornado. É como escreverbool ok = f1() && f2();
ondef2()
é chamado apenas quandof1()
retornatrue
.f2()
ser chamado apenas quandof1()
retornartrue
, o segundo código acima é menos suscetível a erros.f2()
ser sempre chamado),&=
é suficiente:Exemplo para
&=
Além disso, é mais fácil para o compilador otimizar esse código acima do que o código abaixo:
Compare
&&
e&
Podemos nos perguntar se os operadores
&&
e&
obter o mesmo resultado quando aplicados embool
valores?Vamos verificar usando o seguinte código C ++:
Resultado:
Conclusão
Portanto SIM podemos substituir
&&
por&
embool
valores ;-)Então é melhor usar
&=
em vez de&&=
.Podemos considerar
&&=
inútil para os booleanos.O mesmo para
||=
Se um desenvolvedor quiser
f2()
ser chamado apenas quandof1()
retornarfalse
, em vez de:Aconselho a seguinte alternativa mais compreensível:
ou se você preferir tudo em um estilo de linha :
fonte
success = success && DoImportantStuff()
if(success) success = DoImportantStuff()
. Se a declaraçãosuccess &&= DoImportantStuff()
fosse permitida, muitos desenvolvedores pensariam queDoImportantStuff()
sempre é chamado qualquer que seja o valorsuccess
. Espero que isso responda o que você quer saber ... Também melhorei muitas partes da minha resposta. Por favor, diga-me se minha resposta é mais compreensível agora? (sobre o seu comentário propósito) Cheers, Vê-lo ;-)success &&= DoImportantStuff()
fosse permitida, muitos desenvolvedores pensariam queDoImportantStuff()
sempre é chamado de qualquer valor do sucesso". Você pode dizer isso sobre issoif (success && DoImportantStuff())
. Desde que se lembrem da lógica por trás da sintaxe if, eles não devem ter problemas&&=
.f1()
sempre avalia,ok &&= f(1)
mas não presumem que sempre avaliaok = ok && f(1)
. Parece tão provável para mim.v1 += e2
ser o equivalente sintático do açúcar dav1 = v1 + e1
variável v1 e da expressão e2. Apenas uma notação abreviada, só isso.