Heim >Backend-Entwicklung >C++ >Lauert undefiniertes Verhalten in der std::string-Verkettung im Code von Bjarne Stroustrup?

Lauert undefiniertes Verhalten in der std::string-Verkettung im Code von Bjarne Stroustrup?

Susan Sarandon
Susan SarandonOriginal
2024-10-23 18:14:58641Durchsuche

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

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:

  • Der Postfix-Ausdruck wird vor jedem Ausdruck in der Ausdrucksliste sequenziert.
  • Die Initialisierung jedes Parameters ist in Bezug auf die Initialisierung aller Parameter unbestimmt sequenziert anderer Parameter.

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn