std::launder
diberi nama tepat, meskipun hanya jika Anda tahu untuk apa itu. Ia melakukan pencucian memori .
Perhatikan contoh di koran:
struct X { const int n; };
union U { X x; float f; };
...
U u = {{ 1 }};
Pernyataan itu melakukan inisialisasi agregat, menginisialisasi anggota pertama U
dengan {1}
.
Karena n
merupakan const
variabel, kompiler bebas untuk menganggap bahwa u.x.n
harus selalu 1.
Jadi apa yang terjadi jika kita melakukan ini:
X *p = new (&u.x) X {2};
Karena X
sepele, kita tidak perlu menghancurkan objek lama sebelum membuat yang baru sebagai gantinya, jadi ini adalah kode hukum yang sempurna. Objek baru akan memiliki n
anggotanya menjadi 2.
Jadi katakan padaku ... apa yang akan u.x.n
kembali?
Jawaban yang jelas adalah 2. Tapi itu salah, karena kompiler diperbolehkan untuk berasumsi bahwa const
variabel yang benar-benar (bukan hanya a const&
, tetapi variabel objek yang dideklarasikan const
) tidak akan pernah berubah . Tapi kami baru saja mengubahnya.
[basic.life] / 8 menjabarkan keadaan saat OK untuk mengakses objek yang baru dibuat melalui variabel / pointer / referensi ke yang lama. Dan memiliki const
anggota adalah salah satu faktor yang mendiskualifikasi.
Jadi ... bagaimana kita bisa bicara dengan u.x.n
benar?
Kita harus mencuci ingatan kita:
assert(*std::launder(&u.x.n) == 2); //Will be true.
Pencucian uang digunakan untuk mencegah orang melacak dari mana Anda mendapatkan uang Anda. Pencucian memori digunakan untuk mencegah kompiler melacak di mana Anda mendapatkan objek Anda, sehingga memaksa untuk menghindari optimasi yang mungkin tidak berlaku lagi.
Faktor lain yang mendiskualifikasi adalah jika Anda mengubah jenis objek. std::launder
dapat membantu di sini juga:
aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));
[basic.life] / 8 memberi tahu kami bahwa, jika Anda mengalokasikan objek baru dalam penyimpanan yang lama, Anda tidak dapat mengakses objek baru melalui pointer ke yang lama. launder
memungkinkan kita untuk melangkah ke samping itu.
std::launder
?std::launder
digunakan untuk "mendapatkan pointer ke objek yang dibuat dalam penyimpanan yang ditempati oleh objek yang sudah ada dari jenis yang sama, bahkan jika memiliki konst atau referensi anggota."