std :: launderの目的は何ですか?


242

P0137は、関数テンプレートstd::launderを導入し、 共用体、存続時間、およびポインターに関するセクションで標準に多くの多くの変更を加えます。

このペーパーが解決している問題は何ですか?私が認識しなければならない言語の変更は何ですか?そして、私たちは何をしているのlaunderですか?


2
あなたは紙自体について、またはについてstd::launder尋ねていますか?std::launder「constまたは参照メンバーがある場合でも、同じタイプの既存のオブジェクトによって占有されているストレージに作成されたオブジェクトへのポインターを取得する」ために使用されます。
txtechhelp

7
主題に関する有用なリンク。また、この質問stackoverflow.com/questions/27003727/...
ポール・ルーニー

これは現在、VC2017のバージョン15.7.0でリリースされています
Damian

stdによると、ポインタは単純なタイプなので、ローンダリングは何もしません。;)
curiousguy 2018

回答:


250

std::launderそれが何のためにあるかを知っている場合だけですが、適切に名前が付けられています。メモリロンダリングを実行します

論文の例を考えてみましょう:

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

U u = {{ 1 }};

このステートメントは、集計初期化を実行し、Uwithの最初のメンバーを初期化し{1}ます。

のでnあるconst変数は、コンパイラは、その前提として自由であるu.x.nものとし、常に 1になります。

これを行うとどうなりますか?

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

Xはささいなことなので、新しいオブジェクトを作成する前に古いオブジェクトを破棄する必要はないので、これは完全に正当なコードです。新しいオブジェクトのnメンバーは2になります。

だから教えてください...何がu.x.n返りますか?

明白な答えは2です。しかし、コンパイラは真のconst変数(だけでconst&はなく、宣言され たオブジェクト変数constは決して変更されないと想定することができるため、誤りです。しかし、変更しました。

[basic.life] / 8は、変数/ポインタ/古いオブジェクトへの参照を介して、新しく作成されたオブジェクトにアクセスしてもよい状況を詳しく説明しています。そして、const会員を持つことは失格要因の一つです。

では... u.x.n適切に話し合うにはどうすればよいですか?

私たちは自分の記憶を洗濯しなければなりません:

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

マネーロンダリングは、お金をどこから取得したかを人々が追跡できないようにするために使用されます。メモリロンダリングは、コンパイラーがオブジェクトを取得した場所をトレースしないようにするために使用されます。これにより、適用されなくなる可能性のある最適化を回避することが強制されます。

失格要素のもう1つは、オブジェクトのタイプを変更した場合です。std::launderここでも助けることができます:

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

[basic.life] / 8は、古いオブジェクトのストレージに新しいオブジェクトを割り当てると、古いオブジェクトへのポインタを介して新しいオブジェクトにアクセスできないことを示しています。launderそれを回避することができます。


34
それで私のtl; drは正しいですか:「ロンダリングは基本的には非UBタイプのパンニング用」?
druckermanly 2016

13
これが真実である理由を説明できますか?nconst変数であるため、コンパイラはu.x.n常に1であると想定できます。」それは規格のどこにそれを言っていますか?あなたが指摘したまさにその問題は、そもそもそれが誤りであることを私に暗示するように思われるので、私は尋ねます。これは、ここで失敗するas-ifルールの下でのみ真であるべきです。何が欠けていますか?
user541686

10
@Mehrdad [basic.life] / 8: " 元のオブジェクトが占有していた格納場所に新しいオブジェクトが作成された場合[...]元のオブジェクトの名前は新しいオブジェクトを自動的に参照します[...] if:[...]タイプ[...]に、const修飾されたタイプまたは参照タイプの非静的データメンバーが含まれていない[...] "
ecatmur

14
@バリー非常に; アドレスがptr表すT型のオブジェクトが存在しない場合は、launderの前提条件を破るので、結果について話しても意味がありません。
TC

17
@NicolBolas Oneは、SOのサードパーティ言語ユーザーからの回答を際限なく要求するのと同じくらい、supercatが委員会にロビー活動をすることを望んでいるだけです。また、優れた最適化コンパイラは、あなたの正しいソリューションを最適化するmemcpyサポート(つまり、緩いアライメント)のプラットフォーム上でのインプレース再解釈にとにかく
underscore_d
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.