29

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

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;

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

但是,似乎 C++17 中的新更改意味着该代码现在是 UB,除非std::launder在两个reinterpret_casts. reinterpret_cast两个指针类型之间的 a 的结果等价于两个static_casts:第一个指向cv void*,第二个指向目标指针类型。但是 [expr.static.cast]/13 暗示这会产生一个指向原始对象的指针,而不是指向目标类型对象的指针,因为类型Foo的对象在其第一个字节处不能与对象进行指针互转换unsigned char,也不是指针unsigned char的第一个字节处的对象与自身可相互转换。f.zf.z

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

4

1 回答 1

1

你的问题是:

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

不。

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

std::launder通常仅在您以某种运行时方式(例如,通过放置新)更改(或创建)基础对象的情况子集(例如,由于 const 成员)中需要。助记符:对象“脏”,需要“编辑”。std::launder

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

于 2019-06-14T13:24:20.213 回答