Nehmen Sie die folgende Klasse an:
%Vor% Ich weiß, dass dies nicht der beste Weg ist, operator=
zu implementieren, aber das ist absichtlich, denn meine Frage betrifft diese beiden Zeilen:
Kann sein, dass der Compiler <%> m_content = nullptr;
optimiert, obwohl getCopiedContent
nicht als throw()
oder% co_de definiert ist %:
Auf der einen Seite kann der Compiler davon ausgehen, dass, wenn direkt nach noexcept
der Wert von m_content = nullptr;
mit dem Rückgabewert von m_content
überschrieben wird, der gesamte getCopiedContent
-Ausdruck optimiert werden kann. Auf der anderen Seite, wenn der Compiler es optimiert und m_content = nullptr;
eine Ausnahme auslöst, enthält getCopiedContent
einen ungültigen Wert.
Gibt der C ++ - Standard etwas zu diesem Szenario an?
Kann sein, dass der Compiler optimiert wird m_content = nullptr; obwohl getCopiedContent nicht als throw () oder noexcept definiert ist:
Ja. Dies ist eine redundante Operation ohne Nebenwirkungen. Jeder Compiler, der etwas auf sich hält, optimiert den redundanten Speicher. In der Tat müssen Sie wirklich hart arbeiten, damit der redundante Speicher nicht optimiert wird, wie zum Beispiel:
std::atomic
(wenn es atomar ist, müssen Schreibvorgänge an andere Threads übertragen werden) volatile
std::mutex
) aus den gleichen Gründen wie (1) Wenn andererseits der Compiler es optimiert und getCopiedContent eine Ausnahme auslöst, enthält m_content einen ungültigen Wert
Gute Beobachtung. Der Compiler darf im Exception-Handler den Schreibvorgang von nullptr
durchführen. d. h., es kann Anweisungen neu ordnen, um Operationen zu speichern, vorausgesetzt, das Gesamtergebnis war "so, als ob" es nicht gewesen wäre.
Gibt der C ++ - Standard etwas zu einem solchen Szenario an?
Ja. Es hat die "Als-ob" -Regel. Wenn Sie über einen Thread nachdenken, muss das sichtbare Ergebnis sein, "wie wenn" jede Ihrer Anweisungen sequenziell ohne Optimierungen gegen ein nicht-gepuffertes, nicht gepuffertes, sehr einfaches Speichermodell ausgeführt wurde. Beachten Sie, dass kein Computer, der in den letzten 20 Jahren hergestellt wurde, tatsächlich so einfach ist, aber das Ergebnis des Programms muss so aussehen, als ob es das wäre.
Es gibt eine Ausnahme - Kopieren Elision. Nebenwirkungen der Eliminierung redundanter Kopien müssen unter Umständen nicht erhalten werden. Zum Beispiel beim Kopieren von Kopien von temporären Argumenten und während RVO.
Ich glaube, dass dies Beseitigung von toten Geschäften genannt wird.
Ich weiß nicht, ob Compiler-Optimierungen in den Standards enthalten sind, mit Ausnahme der Als-ob-Regel .
Hier ist der Code für Clang für die Eliminierung des toten Speichers. Ссылка Dies wird nur lokale blockieren.
Vielleicht gibt es einige Werkzeuge, die die Funktion inline einbinden und die Analyse als Block-Local ausführen können, um zu sehen, ob dieser Nullptr-Speicher eliminiert werden kann. Offensichtlich würde ein Wurf in der Funktion die Analyse veranlassen, den Nullptr-Speicher zu behalten.
Offensichtlich verstößt das von Ihnen beschriebene Szenario gegen die Als-ob-Regel, so dass es nicht standardkonform ist.
Tags und Links c++ exception compiler-optimization throw