gpt4 book ai didi

c++ - 更改派生类型的对齐方式

转载 作者:太空宇宙 更新时间:2023-11-04 14:33:50 26 4
gpt4 key购买 nike

假设您有这两种类型:

struct alignas(8) Base { double a; double b; }
struct alignas(16) Derived : public Base {}

还有这些函数:

void Foo(Base b)
void Bar(Base* start, Base* end)

像这样打电话合法吗

Foo(someDerived)
Bar(someDerivedArray, someDerivedArray + arrayLength)

在所有情况下?是否依赖于Base的内容和具体的对齐限制?如果 derived 是 32 位对齐的,我绝对可以看出存在问题,因为那样的话 someDerivedArray 的元素之间就会有间隙>Bar 不知道这个差距,所以我认为这是未定义的行为,但我不确定。

XY 解释:我们使用的是 GPGPU 库 Thrust,它的复杂类型在设备代码和主机代码之间对齐不一致;我们正试图弄清楚如何解决这个问题。一种选择是定义我们自己的从 thrust::complex 派生的复杂类型,但使用相同的对齐说明符并使用它,当然各种推力函数都需要 thrust::complex,因此我们将切入或转换为对齐程度较低的类型。

最佳答案

对一个Base*做指针运算,如果指针实际指向一个Derived对象,它总是UB。对齐无关紧要。如果 BaseDerived 具有相同的大小 那么这可能看起来有效,但它仍然是 UB。

将指向 Derived 对象的指针传递给采用 Base*执行指针运算的函数通常没问题,需要注意的是,如果函数将对指针执行 delete,则 Base 必须具有虚拟析构函数。同样,对齐无关紧要。

之所以增加Derived的对齐方式没有区别,是因为它的Base子对象还是强制按照Base的对齐方式对齐。 (这就是为什么一般情况下,您可以增加派生类相对于基类的对齐方式,但不能减少。)所以当 Derived* 转换为 Base*,你仍然得到一个有效的指针值:它指向一个 Base 对象并且该对象正确对齐。 (事实上​​ ,不存在未针对其类型正确对齐的对象。任何创建此类对象的尝试都会导致 UB。)

因此,只要 Foo 不尝试 delete 指针,Foo(someDerived) 通常就没问题,而 Bar(someDerivedArray, someDerivedArray + arrayLength) 不会。

关于c++ - 更改派生类型的对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53843808/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com