Operador ternario?: Vs if… else

80

En C ++, ¿el operador?: Es más rápido que las declaraciones if () ... else? ¿Existen diferencias entre ellos en el código compilado?

Xirdus
fuente
Pregunta difícil, ya que también dependería de la configuración de optimización del compilador.
Extraneon
3
Eso ciertamente depende de lo que hagas dentro de las ramas. El operador condicional solo permite expresiones mientras que ifpermite declaraciones.
Gumbo
4
relacionado: ¿ Ternario o no ternario?
Nick Dandoulakis
8
Un tipo decidió al azar editar mi pregunta de tres años perfectamente correcta, reescribiendo la pregunta para que suene totalmente diferente a mí y agregando un código totalmente innecesario que hace que todo el problema sea inútil porque, gracias al plegado constante, ambas muestras se reducen a un resultado simple = 5 ". Revirtiendo.
Xirdus
Versión de ensamblaje cmov vs jmp stackoverflow.com/questions/14131096/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

88

Depende de su compilador, pero en cualquier compilador moderno generalmente no hay diferencia. Es algo de lo que no debes preocuparte. Concéntrese en la mantenibilidad de su código.

tomate
fuente
1
+1 Para muchas aplicaciones, no vale la pena considerar la diferencia de rendimiento incluso en un compilador de volcado real.
4
Con respecto a la capacidad de mantenimiento del código, preferiría si ... Al menos para mí es más fácil de leer.
Exa
2
@Exa: Depende del contexto. El operador ternario suele ser mejor cuando se inicializa un objeto.
Nemanja Trifunovic
@Nemanja: Por eso dije "Al menos para mí". Solo me refería a la legibilidad del código :)
Exa
1
@kotlinski, no estoy diciendo que un condicional sea menos mantenible que un if. Ambos son más claros en determinadas circunstancias diferentes, como se describe en las respuestas de la pregunta ternaria o no ternaria To vinculada anteriormente.
ptomato
106

No es mas rapido. Hay una diferencia cuando puede inicializar una variable constante dependiendo de alguna expresión:

const int x = (a<b) ? b : a;

No puedes hacer lo mismo con if-else.

Kirill V. Lyadvinsky
fuente
20
@Developer Art: lo que no es posible con una constvariable.
Trabajo
1
Puede crear una variable no constante, asignarla en if / else, luego crear una nueva variable constante y construirla con la variable non-const. Bastante derrochador, pero lejos de ser imposible.
Puppy
7
¿Qué pasa con el bueno max? const int x = max(a,b);funciona bien.
bobobobo
3
@bobobobo ja! Cuando leí tu comentario, pensé que el comando que sugerías era max ? const int x = max(a,b);y pensé: ¡Que demonios es eso! luego lo leí de nuevo y noté que el signo de interrogación no era monoespacio. dado el tema, creo que estaba justificado pensar en el? era parte del comando! :)
dewd
2
Puede utilizar const int x = [&] -> int { if (a < b) return b; else return a; }.
LF
43

He visto a GCC convertir el operador condicional en cmovinstrucciones (movimiento condicional), mientras convierte las ifdeclaraciones en ramas, lo que significa que en nuestro caso, el código era más rápido cuando se usaba el operador condicional. Pero eso fue hace un par de años, y lo más probable es que hoy, ambos se compilen con el mismo código.

No hay garantía de que se compilen con el mismo código. Si necesita el rendimiento, como siempre, mida . Y cuando haya medido y averiguado que 1. su código es demasiado lento, y 2. es este fragmento particular de código el culpable, estudie el código ensamblador generado por el compilador y compruebe usted mismo lo que está sucediendo.

No confíe en reglas de oro como "el compilador siempre generará un código más eficiente si uso el operador condicional".

jalf
fuente
2
+1. Cuando estaba desarrollando para PS3 usando GCC, usar condicionales en lugar de "if" era útil para evitar ramificaciones.
Johan Kotlinski
¿Es esto específico del lenguaje c? El estándar de c ++ dice Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.que aparentemente evita que el compilador genere cmoveinstrucciones.
Joey.Z
2
@zoujyjs no, C tiene la misma regla. Pero bajo la regla como si, el compilador es libre de hacer trampa, siempre que el resultado final sea correcto. Así que mientras no haya efectos secundarios, el compilador puede realizar esta optimización.
jalf
¿Cómo implementar if else con cmov? ¿Un mov al valor 1 + un cmov al valor 2?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
NOTA: Este consejo está desactualizado (cira 2010), no pude reproducirlo en gcc 4.4 o posterior.
ACyclic
15

Son iguales, sin embargo, el operador ternario se puede usar en lugares donde es difícil usar un if / else:

printf("Total: %d item%s", cnt, cnt != 1 ? "s" : "");

Hacer esa declaración con un if / else, generaría un código compilado muy diferente.


Actualización después de 8 años ...

De hecho, creo que esto sería mejor:

printf(cnt == 1 ? "Total: %d item" : "Total: %d items", cnt);

(de hecho, estoy bastante seguro de que puede reemplazar "% d" en la primera cadena con "uno")

James Curran
fuente
8
Ni siquiera necesita un operador ternario:printf("Total: %d item%s", cnt, "s" + (cnt==1));
MSalters
@MSalters pero eso da un doble nulo al final de la cadena, lo que puede ser un problema en otras situaciones donde el doble nulo significa algo (por ejemplo, en un lpStrFiltermiembro de las estructuras OPENFILENAME )
bobobobo
1
@bobobobo: No. %simprime hasta, pero sin incluir el \0de la cadena de origen.
MSalters
@MSalters ¿cómo funciona esto printf("Total: %d item%s", cnt, "s" + (cnt==1));?
Quirk
2
@Quirk: (cnt==1)es verdadero o falso, que se convierte en 0 o 1. "s" es un puntero a una cadena terminada en nulo. Agregar uno omite un carácter (los). Así que imprime "s" o "".
MSalters
3

Independientemente del código compilado, son algo semánticamente diferente. <cond>?<true expr>:<false expr>es una expresión y if..else..es una declaración.

Aunque la sintaxis de la expresión condicional parece incómoda, es algo bueno. Está obligado a proporcionar un <false expr>y se verifica el tipo de las dos expresiones.

El equivalente a if..else..en lenguaje funcional basado en expresiones como Lisp, Haskell está ? :en C ++, en lugar de if..else..declaración.

amdyes
fuente
2

No está obligado a ponerlo todo en una sola línea: -

x = y==1 ?
    2
    :// else
    3;

Es mucho más claro que if / else porque puede ver inmediatamente que ambas ramas conducen a la asignación de x.

QuentinUK
fuente
También puede inicializar una constante
QuentinUK
0

Esperaría que en la mayoría de los compiladores y plataformas de destino, haya casos en los que "si" sea más rápido y casos en los que?: Sea más rápido. También habrá casos en los que una forma sea más o menos compacta que la otra. Los casos que favorezcan una forma u otra variarán entre compiladores y plataformas. Si está escribiendo código de rendimiento crítico en un micro integrado, mire lo que genera el compilador en cada caso y vea cuál es mejor. En una PC "convencional", debido a problemas de almacenamiento en caché, la única forma de ver cuál es mejor es comparar ambas formas en algo parecido a la aplicación real.

Super gato
fuente
0

En CA, el operador ternario "?:" Está disponible para construir expresiones condicionales de la forma

exp1 ? exp2:exp3

donde exp1, exp2 y exp3 son expresiones

por ejemplo

        a=20;
        b=25;
        x=(a>b)?a:b;

        in the above example x value will be assigned to b;

Esto se puede escribir usando la declaración if..else de la siguiente manera

            if (a>b)
             x=a;
             else
             x=b;

** Por tanto, no hay diferencia entre estos dos. Esto para que el programador lo escriba fácilmente, pero para el compilador ambos son iguales. *

ksrao
fuente
0

Durante la reversión de algún código (que no recuerdo, hace unos años) vi una diferencia de una sola línea entre el código de máquina de:? y si-si no. Don't remember much but it is clear that implementation of both is different.

Pero te aconsejo que no elijas uno de ellos por su eficacia, elige según la legibilidad del código o tu conveniencia. Codificación feliz

Pervez Alam
fuente
La diferencia fue que uno de ellos estaba usando goto para ramificar y otro usaba una instrucción nativa saome, no recuerdo cuál estaba usando cuál ..
Pervez Alam
0

Ternary Operator siempre devuelve un valor. Entonces, en una situación en la que desea algún valor de salida del resultado y solo hay 2 condiciones, siempre es mejor usar el operador ternario. Utilice if-else si alguna de las condiciones mencionadas anteriormente no es cierta.

Raheel Afzal
fuente
6
¿Qué es esto exactamente? ¿Sabe usted lo que está hablando?
Quantum
0

Creo que hay situaciones en las que el if en línea puede producir un código "más rápido" debido al alcance en el que trabaja. La creación y destrucción de objetos puede ser costosa, así que considere el siguiente escenario:

class A{
    public:
    A() : value(0) {
        cout << "Default ctor" << endl;
    }
    A(int myInt) : value(myInt)
    {
        cout << "Overloaded ctor" << endl;
    }

    A& operator=(const A& other){
        cout << "= operator" << endl;
        value = other.value; 
    }

    ~A(){
        cout << "destroyed" << std::endl;
    }

    int value;

};


int main()
{
   {
       A a;
       if(true){
           a = A(5);
       }else{
           a = A(10);
       }
   }

   cout << "Next test" << endl;
   {
        A b = true? A(5) : A(10);
   }
   return 0;
}

Con este código, la salida será:

Default ctor                                                                                                                                                                                                                      
Overloaded ctor                                                                                                                                                                                                                   
= operator                                                                                                                                                                                                                        
destroyed                                                                                                                                                                                                                         
destroyed                                                                                                                                                                                                                         
Next test                                                                                                                                                                                                                         
Overloaded ctor                                                                                                                                                                                                                   
destroyed  

Entonces, al insertar el if, ahorramos un montón de operaciones necesarias para mantener avivo en el mismo alcance que b. Si bien es muy probable que la velocidad de evaluación de la condición sea bastante igual en ambos escenarios, cambiar el alcance lo obliga a tener en cuenta otros factores que el en línea le permite evitar.

Eric
fuente
Y qué hay deA a(true ? 5 : 10);
Quest
-1

Ahora no puedo ayudarte con eso, es posible que pueda ayudarte con una pregunta secundaria debajo, ¿quiero usarlo? Si solo desea conocer la velocidad, simplemente ignore mi comentario.

Todo lo que puedo decir es que sea muy inteligente sobre cuándo usar el ternario. : operador. Puede ser una bendición tanto como una maldición para la legibilidad.

Pregúntese si le resulta más fácil de leer antes de usarlo

int x = x == 1 ? x = 1 : x = 1;

if (x == 1)
{
   x = 1
}
else
{
   x = 2
}

if (x == 1)
    x = 1
else
    x = 1

Sí. Parece estúpido hacer que el código sea 100% falso. Pero ese pequeño truco me ayudó a analizar la legibilidad del código. Es la legibilidad del operador que observa en esta muestra, y no el contenido.

Parece limpio, pero también lo hace el asiento de inodoro y el pomo de la puerta promedio.

En mi experiencia, que es limitada, he visto a muy poca gente que realmente pueda extraditar rápidamente la información requerida de un operador ternario, evítelo a menos que esté 100% seguro de que es mejor. Es un dolor arreglarlo cuando también tiene micrófonos, creo

Proclyon
fuente
5
La primera línea probablemente debería leerse int x = x == 1 ? 1 : 2o posiblementeint x = (x == 1) ? 1 : 2
Hasturkun
Mi punto era simplemente mostrar la vista del código, la limpieza de una línea es agradable, sí. Pero si desea ver CONDICIÓN / ASIGNACIÓN, el contenido del código puede ser falso. Si desea detectar lo que es, mire al operador y la ubicación solo. Veo la palabra SI y () sé, ah, esa es una condición. Veo A = B? CONDICIÓN: CONDICIÓN ¿Lo viste de inmediato? La mayoría de las personas que conozco ese programa no lo conocen, quizás sea porque la mayoría de las personas que conozco ese programa son novatos como yo. Tienes razón en que los números son una tontería, ese es el punto.
Proclyon
2
La primera línea definitivamente necesita algunos paréntesis. Quizás "int x = (y == 1)? 0: 1;" o "int x = ((y == 1)? 0: 1);"
supercat
6
Lo siento, pero no tengo problemas para ver la tarea. Si elige complicar demasiado el ejemplo para expresar su punto, ese es su problema. ¿Por qué no escribe en x = x = 1;todas partes y luego se queja de que la tarea es demasiado complicada y debe evitarse?
UncleBens
-4

No, se convierten exactamente en el mismo código ejecutable.

Alex F
fuente
7
-1: ¿En qué versión de qué compilador, en qué plataforma, con qué código?
Puppy
3
DeadMG: compilador VB6, ¡obviamente!
Alex F