Apa tujuan dari std :: mencuci?

242

P0137 memperkenalkan templat fungsi std::launderdan membuat banyak, banyak perubahan pada standar di bagian tentang serikat pekerja, masa pakai, dan petunjuk.

Apa masalah yang dipecahkan makalah ini? Apa saja perubahan pada bahasa yang harus saya ketahui? Dan apa yang akan kita lakukan launder?

Barry
sumber
2
Apakah Anda bertanya tentang kertas itu sendiri atau tentang std::launder? std::launderdigunakan 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."
txtechhelp
7
tautan yang bermanfaat pada subjek. Juga pertanyaan ini stackoverflow.com/questions/27003727/…
Paul Rooney
Ini sekarang telah dirilis di VC2017 dalam versi 15.7.0
Damian
Menurut std, pointer adalah tipe yang sepele sehingga pencucian tidak melakukan apa-apa. ;)
curiousguy

Jawaban:

250

std::launderdiberi 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 Udengan {1}.

Karena nmerupakan constvariabel, kompiler bebas untuk menganggap bahwa u.x.nharus selalu 1.

Jadi apa yang terjadi jika kita melakukan ini:

X *p = new (&u.x) X {2};

Karena Xsepele, kita tidak perlu menghancurkan objek lama sebelum membuat yang baru sebagai gantinya, jadi ini adalah kode hukum yang sempurna. Objek baru akan memiliki nanggotanya menjadi 2.

Jadi katakan padaku ... apa yang akan u.x.nkembali?

Jawaban yang jelas adalah 2. Tapi itu salah, karena kompiler diperbolehkan untuk berasumsi bahwa constvariabel 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 constanggota adalah salah satu faktor yang mendiskualifikasi.

Jadi ... bagaimana kita bisa bicara dengan u.x.nbenar?

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::launderdapat 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. laundermemungkinkan kita untuk melangkah ke samping itu.

Nicol Bolas
sumber
34
Jadi apakah tl; dr saya benar: "pencucian pada dasarnya untuk jenis hukuman non-UB"?
druckermanly
13
Bisakah Anda menjelaskan mengapa ini benar? "Karena nadalah constvariabel, kompiler bebas untuk berasumsi bahwa u.x.nakan selalu menjadi 1." Di mana dalam standar yang tertulis di situ? Saya bertanya karena masalah yang Anda tunjukkan tampaknya menyiratkan kepada saya bahwa itu salah sejak awal. Seharusnya hanya benar di bawah aturan seolah-olah, yang gagal di sini. Apa yang saya lewatkan?
user541686
10
@Mehrdad [basic.life] / 8: " Jika, [...] objek baru dibuat di lokasi penyimpanan yang ditempati objek asli [...] nama objek asli akan secara otomatis merujuk ke objek baru [...] jika: [...] tipe [...] tidak mengandung anggota data non-statis yang tipenya memenuhi syarat atau tipe referensi [...] "
ecatmur
14
@Barry Very; jika tidak ada objek tipe T yang terletak di alamat yang ptrdiwakilkan, maka Anda mematahkan launderprasyarat, jadi tidak ada gunanya membicarakan hasil.
TC
17
@NicolBolas One hanya bisa berharap supercat melakukan lobi sebanyak mungkin kepada Komite karena mereka terus-menerus menuntut jawaban dari sesama pengguna bahasa pihak ketiga di SO. Selain itu, kompiler pengoptimalisasi yang baik akan mengoptimalkan solusi yang benar untuk memcpymenjadi reinterpretasi di tempat pada platform yang didukung (yaitu pelurusan longgar) pula .
underscore_d