首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否将空基类优化对象强制转换为另一种类型?

是否将空基类优化对象强制转换为另一种类型?
EN

Stack Overflow用户
提问于 2019-09-06 13:41:54
回答 1查看 362关注 0票数 4

考虑以下代码:

代码语言:javascript
复制
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的指针合法吗?例如:

代码语言:javascript
复制
std::cout << reinterpret_cast<Foo*>(b1)->x 
          << reinterpret_cast<Foo*>(b2)->x;

如果是的话,是否同样适用于C++20的属性no_unique_address,假设一个实现可以选择将[[no_unique_address]]成员作为空基类来处理?

例如GCC和Clang,但不包括MSVC,目前核实了以下内容:

代码语言:javascript
复制
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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-06 14:05:17

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

实际上,如果您希望成为技术人员,reinterpret_cast可能不会在这方面发挥作用。在他们之间。所以地址是一样的。是的,如果基类和派生类的地址恰好相同,则该地址将被保留。但就C++对象模型而言,这还不够好。

现在,指向基类的指针是指向派生类的可转换指针,但前提是这两个类都是标准布局。这是因为这样的指针是指针-可转换

但是,空基优化不需要标准布局类型。虽然使用EBO需要使用标准布局的类型,但类型可以在违反标准布局类型规则的同时受益于EBO。当然,offsetof只适用于标准布局类型。

因此,就你所提问题的案文而言,这并不一定行得通。

这就把我们带到了no_unique_address。指针-互易性规则明确地说明了标准布局类型的基类/派生类。并且它有一个关于标准布局类型的第一个非静态数据成员(NSDM)的特定语句(它是与包含的对象相互转换的指针)。但是所有其他的NSDM都没有被提及,因此也不是指针-可互换的。

因此,reinterpret_cast是不够好的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57823192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档