jac*_*k X 5 c++ language-lawyer stdlaunder
struct X { int n; };
const X *p = new const X{3}; // #1
new (const_cast<X*>(p)) const X{5}; // #2
const int c = std::launder(p)->n;
Run Code Online (Sandbox Code Playgroud)
假设在 处创建的对象#1名为 ,obj1而在 处创建的对象#2名为obj2。的前提std::launder是
[ptr.launder] p2链接
p代表内存中一个字节的地址A。处于其生命周期内且类型与 T 类似的对象 X 位于地址 A 处。通过结果可访问的所有存储字节都可通过 p (见下文)访问。
如果存在对象 Z,则可以通过指向对象 Y 的指针值访问存储 b 的字节,并且该对象可与 Y 进行指针互换,这样 b 位于 Z 占用的存储空间内,或者如果 Z 则位于直接封闭的数组对象内是一个数组元素。
这个规则有点晦涩难懂。以下解释正确吗?
obj2sizeof(X)将占用以 开头的字节数A。将Y(指向的对象std::launder(p)) 和Z(即obj2) 视为同一个对象,它们是指针可相互转换的,并且sizeof(X)所占用的字节obj2都在 内Z,因此这些字节都可以通过 到达std::launder(p)。也就是说,“通过结果可访问的所有存储字节”。这些字节是否可以通过 到达p?假设Y(即指向的对象p) 和Z是同一个对象obj1,它们也是假设数组的数组元素,根据 [basic.compound] p3
不是数组元素的 T 类型对象被视为属于具有一个 T 类型元素的数组。
由于以 开头的这些字节A都在数组中,该数组Z是该数组的一个元素。因此,我们可以说这些字节都可以通过p?到达。
[basic.compound]/3 不相关。它特别指出它仅适用于指针算术和比较的目的。实际上并不存在该对象的数组。
我认为当您调用 时std::launder,相关地址处有四个对象:obj1、obj1.n和。
和是指针可相互转换的,就像和一样。除了相同对之外的其他组合不能进行指针互换。没有数组对象,因此“如果 Z 是数组元素,则为直接封闭的数组对象”。不相关。obj2obj2.nobj1obj1.nobj2obj2.n
当考虑来自 的可达性时,它仅std::launder(p)指向因此,并且需要像引用中那样考虑。占用 的(不正确的)字节子集,因此它不相关。可到达的字节是 中的字节。除了我特别考虑过的之外,这是对您的考虑的改写。obj2obj2obj2.nZobj2.nobj2obj2obj2.n
p通过完全相同的推理,从(指向)可到达的字节obj1都是 中的字节obj1。
obj1并且obj2具有相同的大小,因此占用完全相同的字节。因此std::launder(p),不会使任何无法从 访问的字节变得可访问p。
| 归档时间: |
|
| 查看次数: |
225 次 |
| 最近记录: |