Heim  >  Artikel  >  Backend-Entwicklung  >  Behält die STL-Methodenverkettung die Auswertungsreihenfolge in C bei?

Behält die STL-Methodenverkettung die Auswertungsreihenfolge in C bei?

Patricia Arquette
Patricia ArquetteOriginal
2024-10-24 03:28:01500Durchsuche

Does STL Method Chaining Preserve Evaluation Order in C  ?

Behält die Verkettung von STL-Methoden in C die Auswertungsreihenfolge bei?

In Bjarne Stroustrups „The C Programming Language“, 4. Auflage, der folgende Codeausschnitt veranschaulicht die Methodenverkettung:

<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 wertet Anweisungen von links nach rechts aus und ändert die Zeichenfolge s schrittweise. Allerdings ist das Verhalten dieses Ausdrucks je nach verwendetem Compiler mehrdeutig:

  • Clang: Die Auswertung erfolgt in der erwarteten Reihenfolge, was zu s wie „Ich habe gehört, dass es nur funktioniert, wenn“ führt Du glaubst daran.
  • GCC: Die Auswertungsreihenfolge ist unvorhersehbar, was dazu führt, dass s einen falschen Wert annimmt.
  • Visual Studio: Ähnlich wie bei GCC ist die Auswertung mehrdeutig und führt oft zum gleichen falschen Ergebnis.

Enthüllung des nicht spezifizierten Verhaltens

Der Code zeigt aufgrund der Unbestimmtheit nicht spezifiziertes Verhalten Reihenfolge der Auswertung von Unterausdrücken, obwohl kein undefiniertes Verhalten aufgerufen wird. Der Kern des Problems liegt in der Auswertungsreihenfolge von Funktionsargumenten innerhalb verketteter Funktionsaufrufe.

Insbesondere für die folgenden Unterausdrücke:

  • s.find("even")
  • s.find(" don't")

Ihre Auswertungsreihenfolge ist unbestimmt in Bezug auf:

  • s.replace(0, 4 , "")

Dies bedeutet, dass die Suchaufrufe vor oder nach dem Ersetzungsaufruf ausgewertet werden können, was sich auf die Länge von s und folglich auf die Ergebnisse der Suchaufrufe auswirkt.

Abbildung mit benutzerdefinierter Suchfunktion

Um diese Mehrdeutigkeit zu veranschaulichen, verwendet eine modifizierte Version des Codes eine benutzerdefinierte my_find-Funktion, die die Position der Suchzeichenfolgen in jeder Unterausdrucksauswertung meldet:

<code class="cpp">std::string::size_type my_find(std::string s, const char *cs) {
  std::string::size_type pos = s.find(cs);
  std::cout << "position " << cs << " found: " << pos << std::endl;
  return pos;
}</code>

Das Ausführen dieses Codes mit verschiedenen Compilern führt je nach Auswertungsreihenfolge zu unterschiedlichen Ergebnissen:

  • Clang: my_find wird auf „gerade“ ausgewertet, bevor es ausgewertet wird für „nicht“, was zur korrekten Ausgabe führt.
  • GCC: my_find wird auf „nicht“ ausgewertet, bevor es auf „gerade“ ausgewertet wird, was zu einem falschen Ergebnis führt .

C 17-Änderungen

Der C 17-Standard (p0145r3) führt Verfeinerungen an den Regeln für die Reihenfolge der Ausdrucksauswertung ein, um diese Mehrdeutigkeit zu beseitigen. Es stärkt die Auswertungsreihenfolge für Postfix-Ausdrücke und ihre Ausdrucksliste wie folgt:

  • Der Postfix-Ausdruck wird vor jedem Ausdruck in der Ausdrucksliste und jedem Standardargument sequenziert.

Dadurch wird sichergestellt, dass verkettete Methodenaufrufe in der erwarteten Reihenfolge ausgewertet werden, wodurch dieses undefinierte Verhalten in C 17 behoben wird.

Das obige ist der detaillierte Inhalt vonBehält die STL-Methodenverkettung die Auswertungsreihenfolge in C bei?. 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