std::launderha un nome appropriato, anche se solo se sai a cosa serve. Esegue il riciclaggio di memoria .
Considera l'esempio nel documento:
struct X { const int n; };
union U { X x; float f; };
...
U u = {{ 1 }};
Tale istruzione esegue l'inizializzazione aggregata, inizializzando il primo membro di Ucon {1}.
Perché nè una constvariabile, il compilatore è libero di assumere che u.x.ndeve sempre essere 1.
Quindi cosa succede se lo facciamo:
X *p = new (&u.x) X {2};
Perché Xè banale, non è necessario distruggere il vecchio oggetto prima di crearne uno nuovo al suo posto, quindi questo è un codice perfettamente legale. Il nuovo oggetto avrà il suo nmembro essere 2.
Allora dimmi ... cosa u.x.ntornerà?
La risposta ovvia sarà 2. Ma questo è sbagliato, perché al compilatore è consentito supporre che una constvariabile veramente (non solo una const&, ma una variabile oggetto dichiarata const ) non cambierà mai . Ma l'abbiamo appena cambiato.
[basic.life] / 8 spiega le circostanze in cui è OK accedere all'oggetto appena creato attraverso variabili / puntatori / riferimenti a quello vecchio. E avere un constmembro è uno dei fattori squalificanti.
Quindi ... come possiamo parlare u.x.ncorrettamente?
Dobbiamo riciclare la nostra memoria:
assert(*std::launder(&u.x.n) == 2); //Will be true.
Il riciclaggio di denaro viene utilizzato per impedire alle persone di rintracciare da dove hai preso i tuoi soldi. Il riciclaggio di memoria viene utilizzato per impedire al compilatore di tracciare da dove proviene l'oggetto, costringendolo in tal modo a evitare eventuali ottimizzazioni che potrebbero non essere più applicabili.
Un altro dei fattori squalificanti è se si modifica il tipo di oggetto. std::launderpuò aiutare anche qui:
aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));
[basic.life] / 8 ci dice che, se si assegna un nuovo oggetto nella memoria di quello vecchio, non è possibile accedere al nuovo oggetto tramite i puntatori al vecchio. launderci consente di fare questo.
std::launder?std::launderviene utilizzato per "ottenere un puntatore a un oggetto creato nella memoria occupata da un oggetto esistente dello stesso tipo, anche se ha membri const o di riferimento".