本文主要讨论c++对像的内存布局。对于一个简单的或者是复杂的c++类,他在内存里到底是怎么储存的呢?
每个类都有数据成员和接口,它们的存储方式一样吗?虚函数为什么会带来存储上的开销?类的静态成员和非静态成员有什么区别呢? 本文将为你揭晓这些问题的答案。
一个空的类:
class Test{
}
c++支持一个空类,这个空类什么定义都没有,什么都不做。那sizeof(Test)是0吗?
答案不是的。sizeof(Test)的大小一般是一。编译器会插入一个占位字节。为什么呢?
给出以下语句:
Test a[10];一个test的数组,如果test的大小是0,那么显然,就没法取得a的每个元素了。
a[0], a[1]地址是一样的,这就产生了矛盾。
既然空类什么都不做,那空类有什么用吗?答案是肯定的。c++的非虚成员函数是单独存放的,所以只有函数的类实际上也是一个空类。而实际应用里,这些类太常见了。另外的一个用途是作为标签类,用在模板里。STL的模板traits就有很多空类。
一个简单的类:
class A{
int x_;
int y_;
int z_;
public :
A(int x, int y,int z): x_(x),y_(y),z_(z) {}
int getx() const { return x_}
}
这个类的内存布局是这样的:
类的内存布局里只有数据成员。
函数成员并没有存在一起。函数成员是单独存放的。为什么可以单独存放?一般的成员函数第一个实际上是隐藏的this指针,这个this指针将函数成员和数据成员联接在一起了。这样就实现了单独存放。
所以对于一个A的实例a,sizeof(a)其实等于三个int的大小。不考虑内存对齐的特殊情况,是3*sizeof(int)