web-dev-qa-db-fra.com

Ordre d'évaluation de l'argument "IF"?

if(a && b)
{
  do something;
}

est-il possible d'évaluer les arguments de droite à gauche (b -> a)?

si "oui", qu'est-ce qui influence l'ordre d'évaluation?

(j'utilise VS2008)

36
winnerrrr

L'ordre d'évaluation est spécifié par la norme et est left-to-right. L'expression la plus à gauche sera toujours évaluée en premier avec le && clause.

Si vous souhaitez que b soit évalué en premier:

if(b && a)
{
  //do something
}

Si les deux arguments sont des méthodes et que vous souhaitez que les deux soient évalués indépendamment de leur résultat:

bool rb = b();
bool ra = a();

if ( ra && rb )
{
  //do something
}
44
Luchian Grigore

Avec C++, seuls quelques opérateurs garantissent l'ordre d'évaluation

  • operator && Évalue d'abord l'opérande gauche et si la valeur est logiquement false alors il évite d'évaluer l'opérande droit. Une utilisation typique est par exemple if (x > 0 && k/x < limit) ... qui évite la division par zéro problème.

  • operator || Évalue d'abord l'opérande gauche et si la valeur est logiquement true alors il évite d'évaluer l'opérande droit. Par exemple, if (overwrite_files || confirm("File existing, overwrite?")) ... ne demandera pas de confirmation lorsque l'indicateur overwrite_files Est défini.

  • operator , Évalue d'abord l'opérande gauche, puis l'opérande droit de toute façon, en retournant la valeur de l'opérande droit. Cet opérateur n'est pas utilisé très souvent. Notez que les virgules entre les paramètres d'un appel de fonction sont des opérateurs de virgule not et l'ordre d'évaluation n'est pas garanti.

  • L'opérateur ternaire x?y:z Évalue d'abord x, puis en fonction de la valeur logique du résultat, il évalue uniquement y ou seulement z.

Pour tous les autres opérateurs, l'ordre d'évaluation n'est pas spécifié.

La situation est en fait pire parce que ce n'est pas que l'ordre n'est pas spécifié, mais qu'il n'y a même pas un "ordre" pour l'expression, et par exemple dans

std::cout << f() << g() << x(k(), h());

il est possible que les fonctions soient appelées dans l'ordre h-g-k-x-f (c'est un peu dérangeant car le modèle mental de l'opérateur << véhicule en quelque sorte l'idée de séquentialité mais en réalité ne respecte la séquence que dans l'ordre les résultats sont mis sur le flux et non dans l'ordre dans lequel les résultats sont calculés).

De toute évidence, les dépendances de valeur dans l'expression peuvent introduire une certaine garantie d'ordre; Par exemple, dans l'expression ci-dessus, il est garanti que k() et h() seront appelés avant x(...) car les valeurs de retour des deux sont nécessaires pour appeler x.

Notez également que les garanties pour &&, || Et , Ne sont valables que pour les opérateurs prédéfinis. Si vous surchargez ces opérateurs pour vos types, ils seront dans ce cas comme des appels de fonction normaux et l'ordre d'évaluation des opérandes ne sera pas spécifié.

56
6502

Dans ce cas, puisque vous utilisez &&, a sera toujours évalué en premier car le résultat est utilisé pour déterminer s'il faut ou non court-circuiter l'expression.

Si a renvoie false, alors b n'est pas autorisé à évaluer du tout.

7
Mysticial

Chaque calcul de valeur et effet secondaire du premier argument (gauche) de l'opérateur AND logique intégré && et de l'opérateur logique OR || || est séquencé avant chaque calcul de valeur et effet secondaire du deuxième argument (à droite).

Lisez ici pour une explication plus exhaustive des règles établies: évaluation de la commande

4
Pacheco

Il évaluera de gauche à droite et court-circuitera l'évaluation s'il le peut (par exemple, si a est évalué à faux, il n'évaluera pas b).

Si vous vous souciez de l'ordre dans lequel ils sont évalués, il vous suffit de les spécifier dans l'ordre d'évaluation souhaité dans votre instruction if.

2
Dylan Smith

Le && L'opérateur évalue toujours son opérande gauche en premier. Par exemple:

if (a && b)
{
   //block of code
}

Si a est false, alors b ne sera pas évalué.

Si vous voulez que b soit évalué en premier et a seulement si b est vrai, écrivez simplement l'inverse:

if (b && a)
{
   //block of code
}
1
sameer