C++ std::launder 的目的是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39382501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:49:56  来源:igfitidea点击:

What is the purpose of std::launder?

c++memoryc++17c++-faqstdlaunder

提问by Barry

P0137introduces the function template std::launderand makes many, many changes to the standard in the sections concerning unions, lifetime, and pointers.

P0137引入了函数模板 std::launder,并对有关联合、生命周期和指针的部分中的标准进行了很多很多更改。

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?

这篇论文要解决什么问题?我必须注意语言的哪些变化?我们在做什么launder

回答by Nicol Bolas

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

std::launder名称恰如其分,但前提是您知道它的用途。它执行内存清洗

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 Uwith {1}.

该语句执行聚合初始化,初始化Uwith的第一个成员{1}

Because nis a constvariable, the compiler is free to assume that u.x.nshall alwaysbe 1.

因为n是一个const变量,编译器是免费的假设,u.x.n始终为1。

So what happens if we do this:

那么如果我们这样做会发生什么:

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

Because Xis 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 nmember be 2.

因为X是微不足道的,我们不需要在创建新对象之前销毁旧对象,所以这是完全合法的代码。新对象的n成员为 2。

So tell me... what will u.x.nreturn?

所以告诉我……什么会u.x.n回来?

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

显而易见的答案是 2。但这是错误的,因为允许编译器假设一个真正的const变量(不仅仅是一个const&,而是一个声明的对象变量const永远不会改变。但我们只是改变了它。

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

[basic.life]/8阐明了可以通过变量/指针/对旧对象的引用访问新创建的对象的情况。拥有const会员是取消资格的因素之一。

So... how can we talk about u.x.nproperly?

那……怎么才能好好说话u.x.n呢?

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 compilerfrom 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::laundercan help here too:

另一个不合格的因素是您是否更改了对象的类型。std::launder也可以在这里提供帮助:

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

[basic.life]/8tells 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. launderallows us to side-step that.

[basic.life]/8告诉我们,如果在旧对象的存储中分配新对象,则无法通过指向旧对象的指针访问新对象。launder允许我们回避这一点。