繁体   English   中英

在标准布局对象(例如,使用 offsetof)中进行指针运算时,我们是否需要使用 std::launder ?

[英]Do we need to use std::launder when doing pointer arithmetic within a standard-layout object (e.g., with offsetof)?

这个问题是对以下问题的跟进: 是否添加到“char *”指针 UB,当它实际上并不指向 char 数组时?

CWG 1314 中,CWG 确认使用unsigned char指针在标准布局对象内执行指针算术是合法的。 这似乎意味着一些类似于链接问题中的代码应该按预期工作:

struct Foo {
    float x, y, z;
};

Foo f;
unsigned char *p = reinterpret_cast<unsigned char*>(&f) + offsetof(Foo, z); // (*)
*reinterpret_cast<float*>(p) = 42.0f;

(为了更清楚,我用unsigned char替换了char 。)

然而,似乎 C++17 中的新变化意味着这段代码现在是 UB,除非在两个reinterpret_cast之后使用std::launder 两个指针类型之间的reinterpret_cast的结果等效于两个static_cast :第一个到cv void* ,第二个到目标指针类型。 但是 [expr.static.cast]/13 暗示这会产生一个指向原始对象的指针,而不是指向目标类型的对象,因为Foo类型的对象在其第一个字节处不能与unsigned char对象进行指针互转换,在fz指针的第一个字节处的unsigned char对象也不能与fz本身相互转换。

我发现很难相信委员会打算做出改变来打破这个非常常见的习惯用法,使所有 pre-C++17 使用offsetof未定义。

你的问题是:

在标准布局对象(例如,使用 offsetof)中进行指针运算时,我们是否需要使用 std::launder ?

不。

std::launder在这种情况下不会改变任何东西,因此与所提供的示例无关( imo edit launder 问题或提出另一个问题)。

std::launder通常只需要在您以某种运行时方式(例如,通过放置新)更改(或创建)底层对象的情况下(例如,由于 const 成员)。 助记符:对象是“脏的”并且需要被std::launder 'ed。

仅使用标准布局类型不会导致您需要使用 std::launder 的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM