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 der Ersetzungsmethode von 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>
Dieser Code zeigt jedoch nicht spezifiziertes Verhalten, anstatt undefiniertes Verhalten aufzurufen.
Der Der Grund für dieses nicht spezifizierte Verhalten liegt in der Reihenfolge der Auswertung, die für Unterausdrücke verketteter Funktionsaufrufe nicht spezifiziert ist. In diesem Fall werden die s.find-Funktionsaufrufe entweder vor oder nach dem ersten s.replace-Aufruf ausgewertet, wodurch sich die Länge der resultierenden Zeichenfolge ändert und sich auf das Ergebnis des nachfolgenden find-Aufrufs auswirkt.
Das Beispiel in der Frage zeigt dies: Bei der Auswertung durch verschiedene Compiler (clang, gcc) werden aufgrund unterschiedlicher Auswertungsreihenfolgen unterschiedliche Ergebnisse erzielt.
Details
Funktionsargumente haben eine nicht spezifizierte Auswertungsreihenfolge und zwar Durch die Verkettung von Funktionsaufrufen wird für jeden Funktionsaufruf eine Auswertungsreihenfolge von links nach rechts eingeführt. Die Argumente jedes Aufrufs werden vorher nur in Bezug auf diesen bestimmten Funktionsaufruf sequenziert.
Im Beispiel Diese Unbestimmtheit entsteht bei der Auswertung von s.find("even") und s.find("don't") in Bezug auf s.replace(0, 4, "").
Ignorieren weiterer Sub -Ausdrucksaufschlüsselungen, 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.
Das obige ist der detaillierte Inhalt vonLauert undefiniertes Verhalten in der std::string-Verkettung im Code von Bjarne Stroustrup?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!