Qual è lo scopo di std :: launder?


242

P0137 introduce il modello di funzione std::laundere apporta molte, molte modifiche allo standard nelle sezioni relative a sindacati, durata e puntatori.

Qual è il problema che questo documento sta risolvendo? Quali sono le modifiche alla lingua di cui devo essere consapevole? E cosa stiamo laundering?


2
Stai chiedendo del documento stesso o su 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".
txtechhelp

7
link utile sull'argomento. Anche questa domanda stackoverflow.com/questions/27003727/…
Paul Rooney,

Questo è stato ora rilasciato in VC2017 nella versione 15.7.0
Damian

Secondo lo standard, i puntatori sono tipi banali, quindi il riciclaggio non fa nulla. ;)
curiousguy il

Risposte:


250

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.


34
Quindi il mio tl; dr è corretto: "il riciclaggio è fondamentalmente per punizioni di tipo non UB"?
druckermanly

13
Potresti spiegare perché questo è vero? "Poiché nè una constvariabile, il compilatore è libero di presumere che u.x.ndebba essere sempre 1." Dove lo dice lo standard? Lo chiedo perché lo stesso problema che hai indicato sembrerebbe implicarmi che sia falso in primo luogo. Dovrebbe essere vero solo sotto la regola as-if, che qui fallisce. Cosa mi sto perdendo?
user541686

10
@Mehrdad [basic.life] / 8: " Se, [...] un nuovo oggetto viene creato nella posizione di archiviazione in cui l'oggetto originale occupato [...] il nome dell'oggetto originale si riferirà automaticamente al nuovo oggetto [...] se: [...] il tipo [...] non contiene alcun membro di dati non statico il cui tipo è qualificato const o un tipo di riferimento [...] "
ecatmur

14
@Barry Very; se non ci sono oggetti di tipo T situati nell'indirizzo ptrrappresenta, allora si infrange launderil presupposto, quindi non ha senso parlare del risultato.
TC

17
@NicolBolas Si può solo sperare che il supercat faccia lobbying nei confronti dei Comitati quanto fanno continuamente richieste impegnative da parte di altri utenti di lingue di terze parti su SO. Inoltre, un buon compilatore ottimizzato sarà ottimizzare la corretta soluzione di memcpyin una rilettura sul posto su piattaforme (ad esempio lassista allineamento) supportati in ogni caso .
underscore_d
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.