是否将指向类的指针强制转换为它的第一个成员非法?

mai*_*mai 4 c++ pointers casting

我在我们的项目中看到一些奇怪的代码,如下所示。我测试它并得到正确的答案。但我认为这是非法的,谁能给我解释一下?

class Member
{
public:
    Member():
        a(0),b(1)
    {}

    int a;
    int b;
};

// contains `Member` as its first member
class Container
{
public:
    Container():
        c(0),d(0)
    {}

    Member getMemb(){return fooObject;}

    Member fooObject;
    int c;
    int d;
};
Run Code Online (Sandbox Code Playgroud)

以及我们如何使用它:

int main()
{
    auto ctain = new Container;
    auto meb = (Member *)ctain; // here! I think this is illegal

    cout << "a is " <<  meb->a << ", b is" << meb->b << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了正确的答案,a是0,b是1。这只是巧合吗?我还注意到如果fooObject不是第一个成员,我会得到错误的答案。

Pas*_* By 7

该片段是合法的。这里的C 风格转换(Member*)实际上是一个reinterpret_cast. 来自[basic.compound]

两个对象a并且b在以下情况下是指针可转换的:

  • 它们是同一个对象,或者

  • 一个是联合对象,另一个是该对象的非静态数据成员,或

  • 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则是该对象的第一个基类子对象,或 [... ]

如果两个对象是指针可互转换的,则它们具有相同的地址,并且可以通过 a 从指向另一个的指针获取指向一个的指针reinterpret_­cast

应特别注意确保它确实是标准布局类型,可能带有static_assert(std::is_standard_layout_v<Container>)

另一方面,如果你只是写了,你可以避开整个惨败 auto meb = &ctain.fooObject;