¿Hay algo "muy malo" que pueda suceder &&=
y ||=
se haya utilizado como azúcar sintáctica para bool foo = foo && bar
y bool foo = foo || bar
?
c++
boolean-operations
Kache
fuente
fuente
x ||= y
más o menos equivalente a C ++x = x ? x : y;
para cualquier tipo? En otras palabras, "establecer en y si aún no está configurado". Eso es considerablemente más útil que C o C ++x ||= y
, que (salvo sobrecarga del operador) haría "establecer x a(bool)y
menos que ya esté configurado". No estoy ansioso por agregar otro operador para eso, parece un poco débil. Solo escribeif (!x) x = (bool)y
. Pero, en realidad, no usobool
suficientes variables como para querer operadores adicionales que solo sean realmente útiles con ese tipo.&&=
o||=
es simplemente que C no los tiene. Estoy razonablemente seguro de que la razón por la que C no los tiene es que la funcionalidad no se consideró lo suficientemente beneficiosa.bool foo = foo || bar;
invocaría un comportamiento indefinido porquefoo
no se inicializa antes de la evaluación defoo || bar
. Por supuesto, esto pretende ser algo asíbool foo = …initialization…; …; foo = foo || bar;
y la pregunta entonces es válida.Respuestas:
A
bool
solo puede sertrue
ofalse
en C ++. Como tal, usar&=
y|=
es relativamente seguro (aunque no me gusta particularmente la notación). Es cierto que realizarán operaciones de bits en lugar de operaciones lógicas (y, por lo tanto, no cortocircuitarán), pero estas operaciones de bits siguen una asignación bien definida, que es efectivamente equivalente a las operaciones lógicas, siempre que ambos operandos sean de tipobool
. 1Al contrario de lo que otras personas han dicho aquí, un
bool
en C ++ nunca debe tener un valor diferente como2
. Al asignar ese valor a abool
, se convertirátrue
según el estándar.La única forma de obtener un valor no válido en a
bool
es usarreinterpret_cast
punteros:Pero dado que este código da como resultado un comportamiento indefinido de todos modos, podemos ignorar este posible problema al conformar el código C ++.
1 Es cierto que esta es una advertencia bastante grande como lo ilustra el comentario de Angew:
La razón es que
b & 2
realiza una promoción de enteros de modo que la expresión es equivalente astatic_cast<int>(b) & 2
, lo que resulta en0
, que luego se convierte de nuevo en abool
. Entonces, es cierto que la existencia de unoperator &&=
mejoraría la seguridad de los tipos.fuente
||
y&&
acceso directo, es decir, el segundo argumento no es operando si el primer operando estrue
(resp.false
para&&
).|
,&
,|=
Y&=
siempre evaluar los dos operandos.&=
para un lado izquierdo de tipobool
, porque es perfectamente posible para el lado derecho para ser de tipo distintobool
(comoislower
u otra función stdlib C que devuelve distinto de cero para cierto valor). Si tuviéramos lo hipotético&&=
, probablemente forzaría la conversión del lado derechobool
, que&=
no es así. En otras palabras,bool b = true; b &= 2;
resulta enb == false
.&&
y&
tienen una semántica diferente:&&
no evaluará el segundo operando si el primer operando esfalse
. es decir, algo comoes seguro pero
no lo es, aunque ambos operandos son de tipo
bool
.Lo mismo es cierto para
&=
y|=
:se comportará de manera diferente a:
fuente
Respuesta corta
Todos los operadores
+=
,-=
,*=
,/=
,&=
,|=
... son la aritmética y proporcionan misma expectativa:Sin embargo, los operadores
&&=
y||=
sería lógico, y estos operadores podrían ser propenso a errores debido a que muchos desarrolladores se pueden esperarfoo()
ser siempre llamaronx &&= foo()
.¿Realmente necesitamos hacer que C / C ++ sea aún más complejo para obtener un atajo
x = x && foo()
?¿Realmente queremos ofuscar más la declaración críptica
x = x && foo()
?¿O queremos escribir código significativo como
if (x) x = foo();
?Respuesta larga
Ejemplo para
&&=
Si el
&&=
operador estaba disponible, entonces este código:es equivalente a:
Este primer código es propenso a errores porque muchos desarrolladores pensarían que
f2()
siempre se llama cualquiera que sea elf1()
valor devuelto. Es como escribirbool ok = f1() && f2();
dondef2()
se llama solo cuandof1()
regresatrue
.f2()
ser llamado solo cuandof1()
regresetrue
, por lo tanto, el segundo código anterior es menos propenso a errores.f2()
ser llamado siempre),&=
es suficiente:Ejemplo para
&=
Además, es más fácil para el compilador optimizar este código anterior que el siguiente:
Compara
&&
y&
Podemos preguntarnos si los operadores
&&
y&
dar el mismo resultado cuando se aplica a losbool
valores?Vamos a verificar usando el siguiente código C ++:
Salida:
Conclusión
Por lo tanto SÍ se puede sustituir
&&
por&
debool
valores ;-)Así que utilice mejor
&=
en lugar de&&=
.Podemos considerarlo
&&=
inútil para los booleanos.Igual por
||=
Si un desarrollador quiere
f2()
ser llamado solo cuandof1()
regresefalse
, en lugar de:Aconsejo la siguiente alternativa más comprensible:
o si prefiere todo en un estilo de línea :
fuente
success = success && DoImportantStuff()
if(success) success = DoImportantStuff()
. Sisuccess &&= DoImportantStuff()
se permitiera la declaración , muchos desarrolladores pensarían queDoImportantStuff()
siempre se llama cualquiera sea el valor desuccess
. Espero que esto responda a lo que te preguntas ... También he mejorado muchas partes de mi respuesta. ¿Dime si mi respuesta es más comprensible ahora? (sobre el propósito de tu comentario) Saludos, nos vemos ;-)success &&= DoImportantStuff()
se permitiera la declaración , muchos desarrolladores pensarían queDoImportantStuff()
siempre se llama cualquiera que sea el valor del éxito". Sinif (success && DoImportantStuff())
embargo, puedes decir eso . Mientras recuerden la lógica detrás de la sintaxis if, no deberían tener problemas&&=
.f1()
siempre se evalúa,ok &&= f(1)
pero no asumirá que siempre se evalúaok = ok && f(1)
. Me parece igual de probable.v1 += e2
ser el equivalente de azúcar sintáctico de lav1 = v1 + e1
variable v1 y la expresión e2. Solo una notación abreviada, eso es todo.