std :: launder的目的是什么? [英] What is the purpose of std::launder?

查看:1111
本文介绍了std :: launder的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



什么是本文解决的问题?我必须意识到的语言的变化是什么?我们是什么? c>

解决方案

std :: launder 是适当命名的,虽然只有当你知道它是什么。



考虑文章中的例子:

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

U u = {{1}};

该语句执行聚合初始化,初始化 U n c>是一个 const 变量,编译器可以随意假设 uxn 始终那么如果我们这样做会发生什么:

  X * p = new(& ux)X {2}; 

因为 X 在创建一个新对象之前销毁旧对象,因此这是完全合法的代码。新对象的 n 成员为2。



请告诉我... uxn return?



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



[basic.life] / 8说明了当通过变量/指针访问新创建的对象或者引用老一。有一个 const 的成员是不合格的因素之一。



那么...我们怎么可以谈论 uxn



我们必须清理我们的记忆:

  assert(* std :: launder(& uxn)== 2); //会是true。 

洗钱是用来防止人们跟踪你从哪里得到你的钱。内存清洗用于防止编译器跟踪您获取对象的位置,从而强制它避免任何不再适用的优化。



另一个不合格的因素是如果你改变对象的类型。 std :: launder 也可以在这里使用:

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

[basic.life] / 8告诉我们,如果你在存储中分配一个新对象旧的,你不能通过指针访问新的对象旧的。 流浪让我们可以一步一步。


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?

解决方案

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.

这篇关于std :: launder的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆