Maison >développement back-end >C++ >Un comportement non défini se cache-t-il dans le chaînage std::string dans le code de Bjarne Stroustrup ?

Un comportement non défini se cache-t-il dans le chaînage std::string dans le code de Bjarne Stroustrup ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-23 18:14:58626parcourir

Does Undefined Behavior Lurk in std::string Chaining in Bjarne Stroustrup's Code?

L'expression de chaînage de std::string dans le code de Bjarne Stroustrup présente-t-elle un comportement non défini ?

Dans la 4e édition de "Le langage de programmation C" de Bjarne Stroustrup , un extrait de code illustre le chaînage à l'aide de la méthode de remplacement de std::string :

<code class="cpp">void f2() {
    std::string s = "but I have heard it works even if you don't believe in it";
    s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");

    assert(s == "I have heard it works only if you believe in it");
}</code>

Ce code présente cependant un comportement non spécifié au lieu d'invoquer un comportement non défini.

Le La raison de ce comportement non spécifié réside dans l'ordre d'évaluation, qui n'est pas spécifié pour les sous-expressions des appels de fonction chaînés. Dans ce cas, les appels à la fonction s.find sont évalués avant ou après le premier appel à s.replace, modifiant la longueur de la chaîne résultante et affectant le résultat de l'appel find suivant.

L'exemple de la question démontre ceci : lorsqu'ils sont évalués par différents compilateurs (clang, gcc), des résultats différents sont obtenus en raison de différents ordres d'évaluation.

Détails

Les arguments de fonction ont un ordre d'évaluation non spécifié, et bien que le chaînage des appels de fonction introduit un ordre d'évaluation de gauche à droite pour chaque appel de fonction, les arguments de chaque appel sont séquencés avant seulement par rapport à cet appel de fonction particulier.

Dans l'exemple, cette indétermination survient dans l'évaluation de s.find("even") et s.find(" don't") par rapport à s.replace(0, 4, "").

Ignorer les sous -les pannes d'expression, la séquence des étapes d'évaluation et leur interdépendance peuvent être décrites comme suit :

Step 1: s.replace(0, 4, "")  // A
Step 2: s.find("even")       // B
Step 3: s.replace(B, 4, "only") // C
Step 4: s.find("don't")      // D
Step 5: s.replace(D, 6, "")   // E

Alors que A est séquencé avant B, qui à son tour est séquencé avant C, il n'y a aucune relation de séquençage entre B et D par rapport à A. En conséquence, D peut être évalué avant ou après A, conduisant à des résultats différents en fonction de la séquence choisie.

C 17 Changements

La norme C 17 renforce l'ordre des règles d'évaluation des expressions postfixées et de leur liste d'expressions, donnant au code en question un comportement bien spécifié. Le séquençage est le suivant :

  • L'expression suffixe est séquencée avant chaque expression dans la liste d'expressions.
  • L'initialisation de chaque paramètre est séquencée de manière indéterminée par rapport à celle de tout autre paramètre.

Par conséquent, en C 17 et versions ultérieures, ce code sera toujours évalué correctement.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn