C++: Memory layout of classes using inheritance

谁说胖子不能爱 提交于 2019-12-07 15:54:03

问题


I know how data will be packed is not specified by the standard. I was just trying to get an idea about the memory layout of classes ( esp. how dynamic_cast<void*> guarantees to return a pointer to the start of the most derived class). I could not think of any explanation about the output of the following code:

struct A{ int a;};
struct B{ int b;};
struct C: public A, public B { int c;};
struct D:public C {int d;};


int main(){
  D* ob=new D;
  A* a = ob;
  B* b = ob;
  C* c = ob;
}

Printing the values of the pointers shows that, a,c,d have always same value, only b is added 4 Bytes as offset. Is it accidental? Or there is a logic behind it?

Edit: Conceptually the layout should be like the image,but somehow the points A,C and D merges to one.


回答1:


First, your struct A is

| int a |

and B is

| int b |

struct C inherits struct A and struct B, and it also has one member, int c. So it can have a layout like this:

            struct B
struct A     /
   \        /
| int a | int b | int c |

and struct D, which inherits struct C, is

            struct B
struct A     /
   \        /
| int a | int b | int c | int d |
\-----------------------/
         struct C

Now think about D* ob = new D;. It'll be like this:

| int a | int b | int c | int d |
^
\
 ob

And think about A* a = ob - struct A is on offset 0 of struct D, So it is

| int a | int b | int c | int d |
^
\
 a

It's equal to struct c.

However, when it comes to struct B, it's on offset 4 (if sizeof(int) == 4), So it's -

| int a | int b | int c | int d |
        ^
        /
       b

Notice that the layout is not defined in standard, and it can be different each implementation. I showed you one of possible layouts.

For an advanced information, I suggest you to read C++ Multiple Inheritance Memory Layout with "Empty classes".




回答2:


Your reasoning is correct. However, the layout is not defined in the standard, so you cannot rely on it. That being said, most compiler will choose the layout you depict in your figure.




回答3:


Printing the values of the pointers shows that, a,c,d have always same value, only b is added 4 Bytes as offset.

In a D object the C sub-object comes first, so it should not be surprising that it has the same address as the complete D object (what are you expecting to come before the C object? Why should there be any extra bytes at the start of the D?)

In a C object the A sub-object comes first, so it should not be surprising that it has the same address as the C object, and therefore if the C is a sub-object of a D, that it also has the same address as the complete D object.

Is it accidental? Or there is a logic behind it?

It's not accidental. It's defined by your compiler's ABI. A number of compilers follow the Itanium C++ ABI which documents how the classes must be laid out.



来源:https://stackoverflow.com/questions/25137705/c-memory-layout-of-classes-using-inheritance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!