Zeigt der Verkettungsausdruck von std::string in Bjarne Stroustrups Code undefiniertes Verhalten?
In Bjarne Stroustrups „The C Programming Language“, 4. Auflage , ein Codeausschnitt veranschaulicht die Verkettung mithilfe des Ersetzens von std::string Methode:
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");
}
Dieser Code zeigt jedoch nicht spezifiziertes Verhalten, anstatt undefiniertes Verhalten aufzurufen.
Der Grund für dieses nicht spezifizierte Verhalten liegt in der Reihenfolge der Auswertung, die nicht spezifiziert ist Unterausdrücke verketteter Funktionsaufrufe. In diesem Fall werden die s.find-Funktionsaufrufe entweder vor oder nach dem ersten s.replace-Aufruf ausgewertet, wodurch die Länge der resultierenden Zeichenfolge geändert und das Ergebnis des nachfolgenden find-Aufrufs beeinflusst wird.
Das Beispiel in der Frage zeigt dies: Bei der Auswertung durch verschiedene Compiler (Clang, GCC) werden aufgrund der unterschiedlichen Auswertung unterschiedliche Ergebnisse erzielt Aufträge.
Details
Funktionsargumente haben eine nicht spezifizierte Auswertungsreihenfolge, und während die Verkettung von Funktionsaufrufen eine Auswertungsreihenfolge von links nach rechts für jeden Funktionsaufruf einführt, die Argumente jedes Aufrufs werden vor nur in Bezug auf diesen bestimmten Funktionsaufruf sequenziert.
Im Beispiel entsteht diese Unbestimmtheit in der Auswertung von s.find("even") und s.find(" don't") in Bezug auf s.replace(0, 4, "").
Unter Ignorierung weiterer Unterausdrucksaufschlüsselungen wird die Die Reihenfolge der Bewertungsschritte und ihre gegenseitige Abhängigkeit können wie folgt dargestellt werden:
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
Während A vor B sequenziert wird, das wiederum vor C sequenziert wird, gibt es keine Sequenzierungsbeziehung zwischen B und D in Bezug auf A. Daher kann D entweder vor oder nach A ausgewertet werden, was je nach gewählter Reihenfolge zu unterschiedlichen Ergebnissen führt.
C 17 Änderungen
Der C 17-Standard stärkt die Reihenfolge der Bewertungsregeln für Postfix-Ausdrücke und ihre Ausdrucksliste und verleiht dem betreffenden Code ein klar spezifiziertes Verhalten. Die Reihenfolge ist wie folgt:
Daher wird dieser Code in C 17 und höher immer korrekt ausgewertet.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3