考虑以下代码:
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));从b1或b2访问到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
发布于 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是不够好的。
https://stackoverflow.com/questions/57823192
复制相似问题