Std :: launder'ın amacı nedir?


242

P0137 , fonksiyon şablonunu sunar std::launderve sendikalar, ömür boyu ve işaretçilerle ilgili bölümlerde standartta birçok, çok değişiklik yapar.

Bu makalenin çözdüğü sorun nedir? Farkında olmam gereken dilde değişiklikler nelerdir? Ve ne yapıyoruz launder?


2
Kağıdın kendisini mi soruyorsunuz std::launder? std::launder"const veya başvuru üyeleri olsa bile, aynı türdeki mevcut bir nesne tarafından işgal edilen depolamada oluşturulan bir nesneye bir işaretçi elde etmek için kullanılır."
txtechhelp

7
konuyla ilgili faydalı link . Ayrıca bu soru stackoverflow.com/questions/27003727/…
Paul Rooney

Bu, VC2017'de 15.7.0 sürümünde yayınlandı
Damian

Std'ye göre, işaretçiler önemsiz türlerdir, bu nedenle aklama hiçbir şey yapmaz. ;)
curiousguy

Yanıtlar:


250

std::launderancak bunun ne için olduğunu biliyorsanız iyi bir şekilde adlandırılır. Bellek aklama gerçekleştirir .

Makaledeki örneği düşünün:

struct X { const int n; };
union U { X x; float f; };
...

U u = {{ 1 }};

Bu ifade, Uile ilk üyesini başlatarak toplam başlatma gerçekleştirir {1}.

Çünkü nbir olan constdeğişken, derleyici varsaymak serbesttir u.x.neder hep 1 olmak.

Peki bunu yaparsak ne olur:

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

Çünkü Xönemsiz olan bu tamamen yasal koddur yüzden biz, onun yerine yenisini oluşturmadan önce eski nesneyi yok etmek gerekmez. Yeni nesnenin nüyesi 2 olacaktır.

Öyleyse söyle bana ... ne u.x.ndönecek?

Açık cevap 2 olacaktır. Ancak bu yanlıştır, çünkü derleyicinin gerçek bir constdeğişkenin (sadece a değil const&, beyan edilen bir nesne değişkeni const) asla değişmeyeceğini varsaymasına izin verilir . Ama biz sadece değiştirdik.

[basic.life] / 8 , yeni oluşturulan nesneye eski değişkene / işaretçilere / referanslara erişmenin uygun olduğu durumları açıklar . Ve bir constüyeye sahip olmak diskalifiye edici faktörlerden biridir.

Peki ... nasıl u.x.ndüzgün bir şekilde konuşabiliriz ?

Hafızamızı aklamak zorundayız:

assert(*std::launder(&u.x.n) == 2); //Will be true.

Kara para aklama, insanların paranızı aldığınız yeri izlemelerini önlemek için kullanılır. Bellek aklama, derleyicinin nesnenizi aldığınız yerden izlemesini önlemek için kullanılır , böylece artık uygulanamayan optimizasyonlardan kaçınmaya zorlar.

Diskalifiye edici faktörlerden bir diğeri, nesnenin türünü değiştirirseniz. std::launderburada da yardımcı olabilir:

aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));

[basic.life] / 8 , eskisinin deposuna yeni bir nesne atarsanız, eski nesneye işaretçilerle yeni nesneye erişemeyeceğinizi söyler. launderbunu yan adım atmamızı sağlar.


34
Yani benim tl; dr doğru: "aklama temelde UB tipi olmayan punning için"?
druckermanly

13
Bunun neden doğru olduğunu açıklayabilir misiniz? " nBir constdeğişken olduğu için derleyici u.x.nher zaman 1 olacağını varsayabilir ." Standartta nerede söylüyor? Soruyorum çünkü belirttiğiniz sorun bana ilk başta yanlış olduğunu ima ediyor gibi görünüyor. Sadece burada başarısız olan as-if kuralı altında doğru olmalıdır. Neyi kaçırıyorum?
user541686

10
@Mehrdad [basic.life] / 8: " Eğer, [...] orijinal nesnenin kapladığı depolama yerinde yeni bir nesne oluşturulursa [...] orijinal nesnenin adı otomatik olarak yeni nesneye atıfta bulunur [...] eğer: [...] [...] türü sabit kalifiye veya referans türü olmayan statik olmayan bir veri elemanı içermiyorsa [...] "
ecatmur

14
@Barry Very; adreste yer alan T türü hiçbir nesne yoksa ptr, o zaman launderön koşulunu ihlal edersiniz , bu nedenle sonuç hakkında konuşmanın bir anlamı yoktur.
TC

17
@NicolBolas Birisi, supercat'in komitelerdeki diğer üçüncü taraf dil kullanıcılarından SO'ya sonsuz talepte bulundukları kadar lobicilik yapmasını umabilir. Ayrıca, iyi bir optimize edici derleyici, doğru çözümünüzü yine dememcpy desteklenen (yani gevşek hizalama) platformlarda yerinde yeniden yorumlamaya optimize edecektir .
underscore_d
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.