P0137 introduce funcția șablon std::spala
și face multe, multe schimbări la standard în secțiunile privind sindicatele, durata de viață, și indicii.
Care este problema acestei lucrări este rezolvarea? Care sunt schimbările în limbă, care trebuie să fie conștienți de? Și ce ne `spala ' ing?
std::spala
este numit pe bună dreptate, însă doar dacă știi ce este's pentru. Se efectuează memorie de spălare.
Luați în considerare exemplul din ziar:
struct X { const int n; };
union U { X x; float f; };
...
U u = {{ 1 }};
Această declarație îndeplinește agregate de inițializare, inițializarea primul membru al " U " cu {1}
.
Pentru că " n " este un const
variabil, compilator este liber să presupunem că u.x.n
se întotdeauna fi 1.
Deci, ceea ce' se întâmplă dacă am face acest lucru:
X *p = new (&u.x) X {2};
Pentru că " X " este banal, nu trebuie să ne distrugă vechiul obiect înainte de a crea unul nou în locul său, astfel încât acesta este perfect legal cod. Noul obiect va avea " n " membru 2.
Deci, spune-mi... ce va u.x.n
schimb?
Răspunsul evident va fi de 2. Dar asta's-a întâmplat, deoarece compilatorul este permis să presupunem că un adevărat const
variabil (nu doar o const&
, ci un obiect variabilă declarate const
) nu se vor schimba niciodată. Dar ne-am schimbat.
[[de bază.viața]/8](http://eel.is/c++proiect/de bază.viața#8) precizează circumstanțele în care este OK pentru a accesa obiectul nou creat prin variabile/indicatori/referințe de la cel vechi. Și cu o const
membru este unul dintre cele excluderii factori.
Deci... cum putem vorbi despre u.x.n
corect?
Trebuie să spele memoria noastră:
assert(*std::launder(&u.x.n) == 2); //Will be true.
Spălarea de bani este folosit pentru a preveni oamenii de la urmărire în cazul în care ți-ai primit banii de la. Memorie de spălare a banilor este utilizat pentru a preveni compilator de contur de unde ai luat obiect, astfel fortandu-l pentru a evita orice optimizări care să nu se mai aplice.
Un alt excluderii factori este dacă schimbați tipul de obiect. std::spala
pot ajuta aici:
aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));
[[de bază.viața]/8](http://eel.is/c++proiect/de bază.viața#8) ne spune că, dacă se aloce un nou obiect în stocare de cel vechi, nu puteți accesa nou obiect prin pointeri la cel vechi. spala
ne permite să side-pasul asta.