首先,对于类中定义的变量,各个编译器内部并没有强制规定成员布局的情况。
只有一些简单的标准:
1 在同一个访问控制标号(public,private,protected)中定义的非static变量在对象的内存布局顺序是按照定义的顺序。
2 不同的访问控制标号下的(非static)成员变量并无先后顺序的要求。
3 编译器可能还会合成一些内部使用的数据成员,比如虚函数表的指针vptr;C++标准并没有规定那些内部产生的指针的位置
在内存中的位置,甚至可以放在其他成员变量之间。
比如如下的类定义:
class Point3d
{
private : int x;
private: int y;
private : int z;
};
在内存布局上x、y、z的布局并没有限制。
class Point3d
{
privtate:
int x,y,z;
};
//在内存布局中x、y、z是按定义顺序一次排列的。
对于上述的编译器内部产生的数据,如vptr,虽然并没有要求其具体存放位置,但是一般的编译器会将其放在对象内存的最开头或者是最后。
如下面的代码(下面的代码可以看出vptr被安放在最开头的位置)。
#include <iostream>
#include <cstdio>
using namespace std;
class Point3d
{
public:
virtual ~Point3d(){}
public:
static Point3d origin;
float x,y,z;
};
int main()
{
cout << sizeof(Point3d) << endl;
printf("&Point3d::x : %p\n" ,&Point3d::x);
printf("&Point3d::y : %p\n" ,&Point3d::y);
printf("&Point3d::z : %p\n" ,&Point3d::z);
}
由于析构函数为虚函数,导致在该类的任何对象中都会生成一个vprt指针,结果显示:
结果显示的是在对象内存布局中的成员变量的偏移量,依次为4,8,12,也就是说第一个位置是vptr;偏移量为0。这也正好验证了类
的大小为16。
参考书籍:深度探索C++对象模型