Si nous avons trois fonctions (foo, bar et baz) qui sont composées comme si ...
foo(bar(), baz())
Le standard C++ garantit-il que la barre sera évaluée avant baz?
Non, il n'y a pas de telle garantie. Ce n'est pas défini selon le standard C++.
Bjarne Stroustrup le dit aussi explicitement dans "Le langage de programmation C++" 3e édition, section 6.2.2, avec un raisonnement:
Un meilleur code peut être généré dans le fichier absence de restrictions d'expression ordre d'évaluation
Bien que, techniquement, cela se réfère à une partie antérieure de la même section qui dit que l’ordre d’évaluation des parties d’une expression est également non défini,.
int x = f(2) + g(3); // undefined whether f() or g() is called first
Il n'y a pas d'ordre spécifié pour bar () et baz () - la seule chose que la norme dit est qu'ils seront tous deux évalués avant que foo () ne soit appelé. A partir de la norme C++, section 5.2.2/8:
L'ordre d'évaluation des arguments n'est pas spécifié.
À partir de [5.2.2] appel de fonction,
L'ordre d'évaluation des arguments n'est pas spécifié. Tous les effets secondaires des évaluations d'expression d'argument prennent effet avant que la fonction ne soit entrée.
Par conséquent, rien ne garantit que bar()
fonctionnera avant baz()
; seuls ces bar()
et baz()
seront appelés avant foo
.
Notez également dans [5] les expressions suivantes:
sauf indication contraire [p. ex. règles spéciales pour
&&
et||
], l'ordre d'évaluation des opérandes d'opérateurs individuels et des sous-expressions d'expressions individuelles, ainsi que l'ordre dans lequel les effets secondaires se produisent, n'est pas spécifié.
ainsi, même si vous demandiez si bar()
sera exécuté avant baz()
dans foo(bar() + baz())
, la commande est toujours non spécifiée.
C++ 17 spécifie un ordre d'évaluation pour les opérateurs non spécifié jusqu'à C++ 17. Voir la question Quelles sont les garanties d'ordre d'évaluation introduites par C++ 17? Mais notez votre expression
foo(bar(), baz())
a encore un ordre d'évaluation non spécifié.
En C++ 11, le texte correspondant se trouve dans 8.3.6 Arguments par défaut/9 (Soulignez moi)
Les arguments par défaut sont évalués chaque fois que la fonction est appelée. L'ordre d'évaluation des arguments de la fonction est non spécifié. Par conséquent, les paramètres d'une fonction ne doivent pas être utilisés dans un argument par défaut, même s'ils ne sont pas évalués.
Le même verbiage est également utilisé par la norme C++ 14 et se trouve sous la même section .
Comme d'autres l'ont déjà fait remarquer, la norme ne donne aucune indication sur l'ordre d'évaluation pour ce scénario particulier. Cet ordre d’évaluation est alors laissé au compilateur, qui peut avoir une garantie.
Il est important de garder à l'esprit que la norme C++ est en réalité un langage permettant d'instruire un compilateur sur la construction de code assembleur/machine. La norme n'est qu'une partie de l'équation. Lorsque la norme est ambiguë ou si elle est définie spécifiquement pour la mise en œuvre, vous devriez vous tourner vers le compilateur et comprendre comment il traduit les instructions C++ en véritable langage machine.
Ainsi, si l'ordre d'évaluation est une exigence, ou au moins une chose importante, et que la compatibilité entre compilateurs croisés n'est pas une exigence, déterminez comment votre compilateur assemblera finalement tout cela, votre réponse pourrait en résulter. Notez que le compilateur pourrait changer sa méthodologie dans le futur