C++ Multiple Inheritance Memory Layout with “Empty classes”

后端 未结 1 931
孤独总比滥情好
孤独总比滥情好 2021-01-02 15:13

I know the memory layout of multiple inheritance is not defined, so I should not rely on it. However, can I rely on it in a special case. That is, a class has only one "

相关标签:
1条回答
  • 2021-01-02 15:38

    In C++11 the compiler is required to use the Empty Base-class Optimization for standard layout types. see https://stackoverflow.com/a/10789707/981959

    For your specific example all the types are standard layout classes and don't have common base classes or members (see below) so you can rely on that behaviour in C++11 (and in practice, I think many compilers already followed that rule, certainly G++ did, and others following the Itanium C++ ABI.)

    A caveat: make sure you don't have any base classes of the same type, because they must be at distinct addresses, e.g.

    struct I {};
    
    struct J : I {};
    struct K : I { };
    
    struct X { int i; };
    
    struct Y : J, K, X { };
    
    #include <iostream>
    
    Y y;
    
    int main()
    {
      std::cout << &y << ' ' << &y.i << ' ' << (X*)&y << ' ' << (I*)(J*)&y << ' ' << (I*)(K*)&y << '\n';
    
    }
    

    prints:

    0x600d60 0x600d60 0x600d60 0x600d60 0x600d61
    

    For the type Y only one of the I bases can be at offset zero, so although the X sub-object is at offset zero (i.e. offsetof(Y, i) is zero) and one of the I bases is at the same address, but the other I base is (at least with G++ and Clang++) one byte into the object, so if you got an I* you couldn't reinterpret_cast to X* because you wouldn't know which I sub-object it pointed to, the I at offset 0 or the I at offset 1.

    It's OK for the compiler to put the second I sub-object at offset 1 (i.e. inside the int) because I has no non-static data members, so you can't actually dereference or access anything at that address, only get a pointer to the object at that address. If you added non-static data members to I then Y would no longer be standard layout and would not have to use the EBO, and offsetof(Y, i) would no longer be zero.

    0 讨论(0)
提交回复
热议问题