web-dev-qa-db-fra.com

Opérateur ternaire?: Vs if ... else

En C++, l'opérateur?: Est-il plus rapide que if () ... else? Y at-il des différences entre eux dans le code compilé?

63
Xirdus

Cela dépend de votre compilateur, mais sur tout compilateur moderne, il n'y a généralement aucune différence. C'est quelque chose dont vous ne devriez pas vous inquiéter. Concentrez-vous sur la maintenabilité de votre code.

81
ptomato

Ce n'est pas plus rapide Il y a une différence lorsque vous pouvez initialiser une variable constante en fonction d'une expression:

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

Vous ne pouvez pas faire la même chose avec if-else.

91

J'ai vu GCC transformer l'opérateur conditionnel en instructions cmov (déplacement conditionnel), tout en transformant des instructions if en branches, ce qui signifie que, dans notre cas, le code était plus rapide lorsque l'opérateur conditionnel était utilisé. Mais c'était il y a quelques années, et très probablement aujourd'hui, les deux compileraient dans le même code.

Rien ne garantit qu'ils compileront dans le même code. Si vous avez besoin de la performance, alors, comme toujours, measure . Et lorsque vous avez mesuré et découvert que 1. votre code est trop lent et 2. que c'est ce morceau de code qui est le coupable, étudiez ensuite le code Assembly généré par le compilateur et vérifiez par vous-même ce qui se passe.

Ne faites pas confiance aux règles d'or telles que "le compilateur générera toujours un code plus efficace si j'utilise l'opérateur conditionnel".

40
jalf

Ils sont identiques, toutefois, l'opérateur ternaire peut être utilisé dans des endroits où il est difficile d'utiliser un if/else:

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

Faire cette déclaration avec un if/else générerait un code compilé très différent.


Mise à jour après 8 ans ...

En fait, je pense que ce serait mieux:

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

(En fait, je suis sûr que vous pouvez remplacer le "% d" dans la première chaîne par "un")

14
James Curran

Juste pour être un peu gaucher ...

x ? y : x = value

assignera value à y si x n'est pas 0 (faux).

2
VS3

Peu importe le code compilé, ce sont des choses sémantiquement différentes. <cond>?<true expr>:<false expr> est une expression et if..else.. est une instruction.

Bien que la syntaxe de l'expression conditionnelle semble maladroite, c'est une bonne chose. Vous êtes obligé de fournir un <false expr> et les deux expressions sont vérifiées.

L'équivalent de if..else.. dans un langage fonctionnel basé sur l'expression tel que LISP, Haskell est ? : en C++, au lieu de l'instruction if..else...

2
amdyes

L'opérateur ternaire retourne toujours une valeur . Ainsi, dans le cas où vous voulez une valeur de sortie du résultat et qu'il n'y a que 2 conditions, il est toujours préférable d'utiliser l'opérateur ternaire . Utilisez if-else si l'une des conditions mentionnées ci-dessus ne le sont pas. vrai.

0
Raheel Afzal

Maintenant, je ne peux pas vous aider avec ça, je pourrais peut-être aider avec une question secondaire en dessous, est-ce que je veux l'utiliser? Si vous voulez juste connaître la vitesse, ignorez simplement mon commentaire.

Tout ce que je peux dire, c'est de bien savoir quand utiliser le ternaire. : opérateur. Cela peut être une bénédiction autant qu'une malédiction pour la lisibilité. 

Demandez-vous si vous trouvez cela plus facile à lire avant de l'utiliser

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

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

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

Oui, il semble stupide de rendre le code 100% faux. Mais cette petite astuce m'a aidé à analyser ma lisibilité du code. C'est la lisibilité de l'opérateur que vous regardez dans cet exemple, et non le contenu. 

Il semble propre, mais le siège de toilette et la poignée de porte ordinaires aussi

D'après mon expérience, qui est limitée, j'ai constaté que très peu de personnes étaient capables d'extrader rapidement les informations requises d'un opérateur ternaire, évitez-les à moins de vous en assurer à 100%. Je pense qu'il est pénible de le réparer quand il y a un problème

0
Proclyon

Vous n'êtes pas obligé de tout mettre sur une seule ligne: -

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

C'est beaucoup plus clair que si/else car vous pouvez voir immédiatement que les deux branches mènent à l'attribution de x.

0
QuentinUK

Je m'attendrais à ce que sur la plupart des compilateurs et des plateformes cibles, il y aura des cas où "si" est plus rapide et des cas où?: Est plus rapide. Il y aura aussi des cas où une forme est plus ou moins compacte que l'autre. Les cas qui favorisent l'une ou l'autre forme varieront entre les compilateurs et les plates-formes. Si vous écrivez du code essentiel à la performance sur un micro intégré, regardez ce que le compilateur génère dans chaque cas et voyez lequel est le meilleur. Sur un PC "grand public", en raison de problèmes de mise en cache, le seul moyen de savoir ce qui est le mieux est de comparer les deux formes sous quelque chose qui ressemble à l'application réelle.

0
supercat

En C, un opérateur ternaire "?:" Est disponible pour construire des expressions conditionnelles de la forme

exp1 ? exp2:exp3

où exp1, exp2 et exp3 sont des expressions

par exemple

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

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

Ceci peut être écrit en utilisant l'instruction if..else comme suit

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

** Donc, il n'y a pas de différence entre ces deux. Ceci pour que le programmeur puisse écrire facilement, mais pour le compilateur, les deux sont identiques. *

0
ksrao

Je pense qu'il y a des situations où l'inline if peut générer un code "plus rapide" en raison de la portée de son fonctionnement. La création et la destruction d'objets peuvent être coûteuses, envisagez le scénario suivant:

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;
}

Avec ce code, le résultat sera:

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

Donc, en ajoutant le if, nous économisons un tas d'opérations nécessaires pour maintenir a au même niveau que b. Bien qu'il soit hautement probable que la vitesse d'évaluation des conditions soit relativement égale dans les deux scénarios, la modification de la portée vous oblige à prendre en compte d'autres facteurs que ceux en ligne, si cela vous permet d'éviter. 

0
Eric

Lors de l'inversion d'un code (dont je ne me souviens plus, il y a quelques années), j'ai constaté une différence d'une ligne à l'autre entre le code de machine: et si-sinon .Don't remember much but it is clear that implementation of both is different.

Mais je vous conseille de ne pas choisir l'un d'eux pour son efficacité, choisissez en fonction de la lisibilité du code ou de votre convenance . Happy Coding

0
Pervez Alam