Mögliche C ++ - Compiler-Optimierung mit / ohne throw / noexcept-Funktion

9

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:

%Vor%

Kann sein, dass der Compiler <%> m_content = nullptr; optimiert, obwohl getCopiedContent nicht als throw() oder% co_de definiert ist %:

%Vor%

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?

    
Alex Lop. 09.11.2015, 13:36
quelle

2 Antworten

4
  

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:

  1. mach es std::atomic (wenn es atomar ist, müssen Schreibvorgänge an andere Threads übertragen werden)
  2. mach es volatile
  3. umgibt das Schreiben mit einer Art Speicherbarriere (z. B. sperre a 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.

    
Richard Hodges 09.11.2015, 13:50
quelle
0

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.

    
Mochan 09.11.2015 15:34
quelle