gpt4 book ai didi

c++ - 将空基类优化对象转换为另一种类型会破坏严格的别名吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:06:24 26 4
gpt4 key购买 nike

考虑以下代码:

struct Base1 { };
struct Base2 { };

struct Foo : Base1, Base2 {
int x;
};

Foo f;
Base1* b1 = &f; // ok, standard upcasting
Base2* b2 = &f; // ok, standard upcasting

// check that the empty base class optimization applies
assert(((void*)b1) == ((void*)&f));
assert(((void*)b2) == ((void*)&f));
assert(((void*)b1) == ((void*)b2));

b1b2 访问指向 foo 的指针是否合法?例如

std::cout << reinterpret_cast<Foo*>(b1)->x 
<< reinterpret_cast<Foo*>(b2)->x;

如果是,是否同样适用于 C++20 的属性 no_unique_address,假设实现选择将 [[no_unique_address]] 成员视为它对待空基类?

例如GCC 和 Clang,但不是 MSVC,当前验证以下内容:

struct Foo {
int x;
[[no_unique_address]] Base1 b1;
char y;
[[no_unique_address]] Base2 b2;
};

static_assert(offsetof(Foo, b1) == 0));
static_assert(offsetof(Foo, b2) == 0));

所以 b1 和 b2 都有它们父对象的地址,可以在这里验证:https://gcc.godbolt.org/z/NF9ACy

最佳答案

您不需要reinterpret_cast 或“空基优化”来从基类转换为派生类。这完全可以通过 static_cast 实现,只要指针指向派生类类型的对象(并且不使用 virtual 继承)。这是标准的 C++98 内容。

确实,如果您希望成为技术人员,reinterpret_cast 可能对此不起作用。 reinterpret_casting between two pointers works as if by doing a cast to a void* between them .所以地址将是相同的。是的,如果基类和派生类的地址恰好相同,则该地址将被保留。但就 C++ 对象模型而言,这还不够好。

现在,指向基类的指针可以与派生类相互转换,但仅当两个类都是标准布局时。这是因为这样的指针是 pointer-interconvertible .

但是 empty-base-optimization 并不需要标准布局类型。尽管需要标准布局类型才能使用 EBO,但违反标准布局类型规则的类型可以从 EBO 中受益。当然,offsetof 仅适用于标准布局类型。

就您提出的问题的文本而言,不能保证有效。

这将我们带到 no_unique_address。指针互换性规则明确说明了标准布局类型的基类/派生类。并且它有一个关于标准布局类型的第一个非静态数据成员(NSDM)的特定声明(它可以与包含的对象进行指针互换)。但所有其他 NSDM 均未提及,因此它们不是指针可相互转换的。

因此,reinterpret_cast 还不够好。

关于c++ - 将空基类优化对象转换为另一种类型会破坏严格的别名吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57823192/

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