What is the purpose of std::launder?

≯℡__Kan透↙ 提交于 2019-11-26 06:54:25

问题


P0137 introduces the function template std::launder and makes many, many changes to the standard in the sections concerning unions, lifetime, and pointers.

What is the problem this paper is solving? What are the changes to the language that I have to be aware of? And what are we laundering?


回答1:


std::launder is aptly named, though only if you know what it's for. It performs memory laundering.

Consider the example in the paper:

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

U u = {{ 1 }};

That statement performs aggregate initialization, initializing the first member of U with {1}.

Because n is a const variable, the compiler is free to assume that u.x.n shall always be 1.

So what' happens if we do this:

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

Because X is trivial, we need not destroy the old object before creating a new one in its place, so this is perfectly legal code. The new object will have its n member be 2.

So tell me... what will u.x.n return?

The obvious answer will be 2. But that's wrong, because the compiler is allowed to assume that a truly const variable (not merely a const&, but an object variable declared const) will never change. But we just changed it.

[basic.life]/8 spells out the circumstances when it is OK to access the newly created object through variables/pointers/references to the old one. And having a const member is one of the disqualifying factors.

So... how can we talk about u.x.n properly?

We have to launder our memory:

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

Money laundering is used to prevent people from tracing where you got your money from. Memory laundering is used to prevent the compiler from tracing where you got your object from, thus forcing it to avoid any optimizations that may no longer apply.

Another of the disqualifying factors is if you change the type of the object. std::launder can help here too:

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

[basic.life]/8 tells us that, if you allocate a new object in the storage of the old one, you cannot access the new object through pointers to the old. launder allows us to side-step that.



来源:https://stackoverflow.com/questions/39382501/what-is-the-purpose-of-stdlaunder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!