Y, O lógico: ¿Está garantizada la evaluación de izquierda a derecha?

3 minutos de lectura

Y, O lógico: ¿Está garantizada la evaluación de izquierda a derecha?
orlp

Es la evaluación de izquierda a derecha de los operadores lógicos (&& ||) garantizado?

Digamos que tengo esto:

SDL_Event event;

if (SDL_PollEvent(&event)) {
    if (event.type == SDL_QUIT) {
            // do stuff
    }
}

¿Se garantiza que esto sea lo mismo que esto?

SDL_Event event;

if (SDL_PollEvent(&event) && event.type == SDL_QUIT) {
    // do stuff
}

Esto también puede ser muy importante, digamos que tenemos dos requisitos, a y b. Requisito a es mucho más probable que falle entonces b. Entonces es más eficiente decir if (a && b) que if (b && a).

  • Un uso clásico e importante para la secuencia implicada por && está probando punteros nulos antes de su uso: if (a != 0 && a->b != 0 && a->b->c != 0) { somefunc(a->b->c->d); }. La secuencia es fundamental para evitar volcados de núcleo. (¡Y estoy ignorando la Ley de Deméter a efectos de exposición!)

    –Jonathan Leffler

    15 abr.


  • @Jonathan: ¡Lo ignoro con el propósito de hacer cualquier trabajo!

    –Steve Jessop

    15 abr.

  • Estos no son operadores de “comparación”.

    – Ben Voigt

    25 jul.

Y, O lógico: ¿Está garantizada la evaluación de izquierda a derecha?
Mateo Italia

Sí, está garantizado, de lo contrario dichos operadores perderían gran parte de su utilidad.

Noticia importante: esto es válido solo para el incorporado && y ||; si algún delincuente los sobrecarga, se los trata como operadores binarios sobrecargados “regulares”, por lo que en este caso ambos los operandos son siempre evaluados y en un orden no especificado como de costumbre. Por esta razón, nunca los sobrecargue: rompe una suposición muy importante sobre el flujo de control del programa.


Cotizaciones estándar relevantes

Incorporado && y || tienen un comportamiento de cortocircuito garantizado

§5.14 ¶1

a diferencia de &, && garantiza la evaluación de izquierda a derecha: el segundo operando no se evalúa si el primer operando es false.

§5.15 ¶1

a diferencia de |, || garantiza la evaluación de izquierda a derecha; además, el segundo operando no se evalúa si el primer operando se evalúa como true.

Si están sobrecargados, se comportan como operadores binarios “normales” (sin cortocircuito ni orden de evaluación garantizado)

§13.5 ¶9

Los operadores que no se mencionan explícitamente en las subcláusulas 13.5.3 a 13.5.7 actúan como operadores binarios y unarios ordinarios que obedecen las reglas de 13.5.1 o 13.5.2.

y && y || no se mencionan explícitamente en estas subcláusulas, por lo que la §13.5.2 regular se cumple:

§13.5.2 ¶1

Un operador binario se implementará mediante una función miembro no estática (9.3) con un parámetro o mediante una función no miembro con dos parámetros. Así, para cualquier operador binario @, x@y se puede interpretar como x.operator@(y) o operator@(x,y).

sin disposición especial para evaluar sólo un lado o en un orden particular.

(todas las citas del estándar C++ 11)

  • Por cierto, tenga en cuenta que, si tiene condiciones “simples” (por ejemplo, la segunda), la bifurcación puede costar más que evaluar la condición en sí.

    – Mateo Italia

    15 abr.

  • Mateo Italia: a y b eran hipotéticos. podrían haber sido IsPrime(n) y IsEven(n), en el que el orden correcto es bastante obvio y se pueden hacer importantes ahorros.

    – orlp

    15 abr.

  • @nightcracker: claro, solo estaba señalando un error pequeño pero común. 🙂

    – Mateo Italia

    15 abr.

  • Las condiciones sin efectos secundarios se pueden mover a cualquier lugar que desee el compilador. El compilador puede eliminar una rama.

    – Patatas

    15 abr.

  • @MatteoItalia: es muy importante tener en cuenta que si anula operator&& o operator|| entonces se trata como una llamada de función regular y la evaluación de izquierda a derecha ya no está garantizada.[

    – Mooing Duck

    Jul 25 ’17 at 22:17

.

¿Ha sido útil esta solución?