"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > 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 ?

Publié le 2024-11-11
Parcourir:980

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 "The C Programming Language" de Bjarne Stroustrup , un extrait de code illustre le chaînage à l'aide du remplacement de std::string méthode :

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

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

La raison de ce comportement non spécifié réside dans l'ordre d'évaluation, qui n'est pas spécifié pour sous-expressions d’appels de fonctions 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 des différents ordres d'évaluation.

Détails

Fonction les arguments 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 apparaît lors de l'évaluation de s.find("even") et s.find(" don't") par rapport à s.replace(0, 4, "").

En ignorant les autres répartitions des sous-expressions, 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 Modifications

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 postfixée est séquencée avant chaque expression de la liste d'expressions.
  • L'initialisation de chaque paramètre est séquencée de manière indéterminée par rapport à celle de n'importe quel paramètre. autre paramètre.

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

Déclaration de sortie Cet article est réimprimé à l'adresse : 1729674849. En cas d'infraction, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3