C++多继承中的内存布局(2)
接上文,还是先看一个例子:
struct base { int value = 99; }; struct offset { char space[10] = "abc"; }; struct derived : offset, base { int dvalue = 0; };
derived的内存布局应该是先存放offset的内容,再存放base的内容,最后存放derived自己的成员,按照4字节对齐,这个很容易验证:
如果我们添加虚函数:
struct base { int value = 99; virtual void foo() { std::cout << value << std::endl; } virtual void bar() { std::cout << value << std::endl; } }; struct offset { char space[10] = "abc"; }; struct derived : offset, base { int dvalue = 0; virtual void foo() { std::cout << value << "," << dvalue << std::endl; } };
这个时候便不再是先存放space的内容了,因为内存最开始的地方要存放vptr,且由于只有base有虚函数,因此可以共用这个vptr,所以在内存布局上会把base放到前面来,按8字节对齐:
且此时,在第二个block中,存放value后还剩四个字节,可以继续存放space的4个char,这个被称作"tail padding"。
验证一下:
typedef long long u64; derived d; base * b = &d; // This generates an offset cout << sizeof(derived) << endl; // cout << *((int*)((u64*)(b) + 1)) <<endl; cout << *((int*)((u64*)(b) + 3)) <<endl; cout << *((char*)((u64*)(b) + 1) + 4) <<endl;
按照上述分析,应该输出:32,99,0,a:
#面试##面经##笔经##C++##面试题刺客退退退#