P0137 引入了函数模板 std::launder
并在有关联合、生命周期和指针的部分对标准进行了许多更改。
这篇论文要解决什么问题?我必须注意的语言变化是什么?我们是什么 launder
ing?
原文由 Barry 发布,翻译遵循 CC BY-SA 4.0 许可协议
P0137 引入了函数模板 std::launder
并在有关联合、生命周期和指针的部分对标准进行了许多更改。
这篇论文要解决什么问题?我必须注意的语言变化是什么?我们是什么 launder
ing?
原文由 Barry 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.5k 阅读
1 回答3.3k 阅读
std::launder
的名字恰如其分,但前提是您知道它的用途。它执行 _内存清洗_。考虑论文中的示例:
该语句执行聚合初始化,用
{1}
初始化U
的第一个成员。因为
n
是一个const
变量,编译器可以自由假设u.x.n
应该 总是 1。那么如果我们这样做会发生什么:
因为
X
是微不足道的,我们不需要在创建新对象之前销毁旧对象,所以这是完全合法的代码。新对象的n
成员为 2。那么告诉我……
u.x.n
会返回什么?显而易见的答案是 2。但这是错误的,因为允许编译器假定真正的
const
变量(不仅仅是const&
,而是 声明 的对象变量const
) _永远不会改变_。但我们只是改变了它。[basic.life]/8 说明了可以通过变量/指针/对旧对象的引用访问新创建的对象的情况。拥有
const
成员是取消资格的因素之一。那么……我们怎样才能正确地谈论
u.x.n
?我们必须清洗我们的记忆:
洗钱是用来防止人们追踪你的钱从哪里来的。内存清洗用于防止 编译器 跟踪您从何处获取对象,从而强制它避免任何可能不再适用的优化。
另一个不合格的因素是您是否更改了对象的类型。
std::launder
也可以在这里提供帮助:[basic.life]/8 告诉我们,如果在旧对象的存储中分配新对象,则无法通过指向旧对象的指针访问新对象。
launder
允许我们回避这一点。