P0137 führt die Funktionsvorlage ein std::launder
und nimmt in den Abschnitten zu Gewerkschaften, Lebensdauer und Zeigern viele, viele Änderungen am Standard vor.
Was ist das Problem, das dieses Papier löst? Was sind die Änderungen an der Sprache, die ich beachten muss? Und was machen wir launder
?
std::launder
?std::launder
wird verwendet, um "einen Zeiger auf ein Objekt zu erhalten, das im Speicher erstellt wurde, der von einem vorhandenen Objekt desselben Typs belegt wird, selbst wenn es Konstanten- oder Referenzelemente enthält."Antworten:
std::launder
wird treffend benannt, allerdings nur, wenn Sie wissen, wofür es ist. Es führt Speicherwäsche durch .Betrachten Sie das Beispiel in der Arbeit:
Diese Anweisung führt eine aggregierte Initialisierung durch und initialisiert das erste Mitglied von
U
with{1}
.Da
n
eine istconst
variabel, ist der Compiler frei davon ausgehen , dassu.x.n
muss immer 1 sein.Was passiert also, wenn wir dies tun:
Da dies
X
trivial ist, müssen wir das alte Objekt nicht zerstören, bevor wir an seiner Stelle ein neues erstellen. Dies ist also ein vollkommen gesetzlicher Code. Dasn
Mitglied des neuen Objekts ist 2.Also sag mir ... was wird
u.x.n
zurückkehren?Die offensichtliche Antwort lautet 2. Aber das ist falsch, da der Compiler davon ausgehen darf, dass sich eine echte
const
Variable (nicht nur eineconst&
, sondern eine deklarierte Objektvariableconst
) niemals ändern wird . Aber wir haben es einfach geändert.[basic.life] / 8 beschreibt die Umstände, unter denen der Zugriff auf das neu erstellte Objekt über Variablen / Zeiger / Verweise auf das alte Objekt in Ordnung ist. Und ein
const
Mitglied zu haben, ist einer der disqualifizierenden Faktoren.Also ... wie können wir
u.x.n
richtig darüber reden ?Wir müssen unser Gedächtnis waschen:
Geldwäsche wird verwendet, um zu verhindern, dass Personen nachverfolgen, woher Sie Ihr Geld haben. Die Speicherwäsche wird verwendet, um zu verhindern, dass der Compiler nachverfolgt, woher Sie Ihr Objekt haben, und um Optimierungen zu vermeiden, die möglicherweise nicht mehr zutreffen.
Ein weiterer disqualifizierender Faktor ist, wenn Sie den Typ des Objekts ändern.
std::launder
kann auch hier helfen:[basic.life] / 8 sagt uns, dass Sie, wenn Sie ein neues Objekt im Speicher des alten Objekts zuweisen, nicht über Zeiger auf das alte auf das neue Objekt zugreifen können.
launder
erlaubt uns, das zu umgehen.quelle
n
es sich um eineconst
Variable handelt, kann der Compiler davon ausgehen, dass dieseu.x.n
immer 1 sein soll." Wo steht im Standard das? Ich frage, weil genau das Problem, auf das Sie hingewiesen haben, mir zu implizieren scheint, dass es überhaupt falsch ist. Es sollte nur unter der Als-ob-Regel wahr sein, die hier fehlschlägt. Was vermisse ich?ptr
, brechen Sie dielaunder
Vorbedingung, sodass es keinen Sinn macht, über das Ergebnis zu sprechen.memcpy
in eine direkten Umdeutung zu unterstützten (dh lax Ausrichtung) Plattformen sowieso .