Aktualisiert, siehe unten!
Ich habe gehört und gelesen, dass C++0x einem Compiler erlaubt, "Hello" für den folgenden Ausschnitt zu drucken
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
Es hat offenbar etwas mit Threads und Optimierungsmöglichkeiten zu tun. Es sieht so aus, als ob dies viele Leute überraschen kann.
Hat jemand eine gute Erklärung dafür, warum dies notwendig war, um dies zu erlauben? Zum Vergleich: Der jüngste C++0x-Entwurf sagt unter 6.5/5
Eine Schleife, die im Falle einer for-Anweisung außerhalb der for-init-Anweisung liegt,
- ruft keine Bibliotheks-E/A-Funktionen auf, und
- nicht auf flüchtige Objekte zugreift oder sie verändert, und
- keine Synchronisationsoperationen (1.10) oder atomare Operationen (Klausel 29) durchführt
kann von der Implementierung als beendet angenommen werden. [Hinweis: Dies soll Compiler-Transformationen ermöglichen. mationen, wie z.B. das Entfernen von Leerschleifen, zu ermöglichen, auch wenn die Terminierung nicht nachgewiesen werden kann. - end note ]
Edita:
Dieser aufschlussreiche Artikel sagt über diesen Standardtext
Leider werden die Worte "undefiniertes Verhalten" nicht verwendet. Immer wenn es in der Norm heißt: "Der Compiler kann P annehmen", wird damit impliziert, dass ein Programm, das die Eigenschaft not-P hat, eine undefinierte Semantik aufweist.
Ist das korrekt, und darf der Compiler "Bye" für das obige Programm ausgeben?
Es gibt eine noch aufschlussreichere Thread hier , in dem es um eine analoge Änderung zu C geht, die von dem Kerl aus dem oben verlinkten Artikel angestoßen wurde. Neben anderen nützlichen Fakten stellen sie eine Lösung vor, die auch für C++0x zu gelten scheint ( Update : Dies wird mit n3225 nicht mehr funktionieren - siehe unten!)
endless:
goto endless;
Ein Compiler darf das nicht wegoptimieren, weil es sich nicht um eine Schleife, sondern um einen Sprung handelt. Ein anderer Mann fasst die vorgeschlagene Änderung in C++0x und C201X zusammen
Indem der Programmierer eine Schleife schreibt, behauptet er entweder dass die Schleife etwas mit sichtbarem Verhalten tut (E/A durchführt, auf flüchtige Objekte oder führt Synchronisierungs- oder atomare Operationen durch), oder dass sie schließlich beendet wird. Wenn ich diese Annahme verletze indem ich eine Endlosschleife ohne Seiteneffekte schreibe, belüge ich den Compiler an, und das Verhalten meines Programms ist undefiniert. (Wenn ich Glück habe, warnt mich der Compiler vielleicht davor.) Die Sprache bietet keine (nicht mehr?) eine Möglichkeit, eine Endlosschleife ohne sichtbares Verhalten auszudrücken.
Aktualisierung am 3.1.2011 mit n3225: Der Ausschuss hat den Text nach 1.10/24 verschoben und sagt
Bei der Implementierung kann davon ausgegangen werden, dass jeder Thread irgendwann eine der folgenden Aktionen ausführt:
- terminieren,
- einen Aufruf an eine Bibliotheks-E/A-Funktion machen,
- auf ein flüchtiges Objekt zuzugreifen oder es zu verändern, oder
- eine Synchronisationsoperation oder eine atomare Operation durchführen.
En goto
Trick wird no nicht mehr funktionieren!