在标准布局对象(例如,使用offsetof)内进行指针算术时,我们需要使用std :: launder吗? [英] Do we need to use std::launder when doing pointer arithmetic within a standard-layout object (e.g., with offsetof)?

查看:343
本文介绍了在标准布局对象(例如,使用offsetof)内进行指针算术时,我们需要使用std :: launder吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题是针对以下问题的后续措施:

This question is a follow-up to: Is adding to a "char *" pointer UB, when it doesn't actually point to a char array?

CWG 1314 中,CWG确认使用unsigned char指针在标准布局对象中执行指针算术是合法的.这似乎意味着某些与链接的问题中的代码相似的代码应按预期的方式工作:

In CWG 1314, CWG affirmed that it is legal to perform pointer arithmetic within a standard-layout object using an unsigned char pointer. This would appear to imply that some code similar to that in the linked question should work as intended:

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.)

(I have replaced char with unsigned char for greater clarity.)

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

However, it seems that the new changes in C++17 imply that this code is now UB unless std::launder is used after both reinterpret_casts. The result of a reinterpret_cast between two pointer types is equivalent to two static_casts: the first to cv void*, the second to the destination pointer type. But [expr.static.cast]/13 implies that this produces a pointer to the original object, not to an object of the destination type, since an object of type Foo is not pointer-interconvertible with an unsigned char object at its first byte, nor is an unsigned char object at the first byte of f.z pointer-interconvertible with f.z itself.

我很难相信委员会打算进行更改以打破这种非常普遍的习惯用法,从而使offsetof的所有C ++ 17以前的用法都不确定.

I find it hard to believe that the committee intended a change that would break this very common idiom, making all pre-C++17 usages of offsetof undefined.

推荐答案

您的问题是:

在一个指针内进行指针算术时,我们需要使用std :: launder吗? 标准布局对象(例如,具有offsetof的对象)?

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

否.

std::launder在这种情况下不会更改任何内容,因此与所提供的示例无关( imo 在问题之外编辑洗钱或提出其他问题).

std::launder won't change anything in this case and therefore has nothing to do with the presented example (imo edit launder out of the question or ask another question).

std::launder通常仅在某些情况下才需要使用(例如,由于const成员所致),在这种情况下,您需要在某些运行时基础对象 >方式(例如,通过新的展示位置).助记符:该对象是脏"的,需要std::launder编辑.

std::launder is usually just needed in a subset of cases (eg. due to a const member) where you change (or create) an underlying object in some runtime manner (eg. via placement new). Mnemonic: the object is 'dirty' and needs to be std::launder'ed.

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

这篇关于在标准布局对象(例如,使用offsetof)内进行指针算术时,我们需要使用std :: launder吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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