3.2 Data Member的布局

来源:互联网 发布:儿童学英语软件 编辑:程序博客网 时间:2024/06/10 01:05

一、预热

在讨论Data Member布局之前,先看比较常见的笔试题目:
1、 空class

    class X{};

sizeof(X) : 1。空的class中没有任何data member,大小不应该是0吗?大小之所以为1,是因为编译器安插进去一个char,所以空class实际上隐藏1字节的大小。
2、没有virtual 成员函数的class

class Point3d{public:    // ...private:    float x, y, z;};

sizeof(Point3d) : 4 + 4 + 4 = 12。float占用4个字节,该类定义了三个float类型的data member,大小为12毫无悬念。
3、含有virtual成员函数的class

class Point3d{public:    virtual void vir_func() { }private:    float x, y, z;};

sizeof(Point3d) : 12 + 4 = 16。其中的4个字节是怎么回事?这一点需要特别注意,编译器还可能会合成一些内部使用的data members,以支持整个对象模型。vptr就是这样的东西,目前所有的编译器都会把它(指向虚表的指针(指针占4个字节)vptr)安插在“内含virtual function之class”的object中。
4、比较混合的class

class Point3d{public:    virtual void vir_func() {}    virtual void vir_func2() {}    void func_test() { }private:    float x;    static list<Point3d*> *freeList;    float y;    static const int chunkSize = 250;    float z;};

sizeof(Point3d) : 12 + 4 = 16。哦?class Point3d含有两个virtual functions,为什么没有两个4字节被计算呢?傻啊,“指向虚表的指针vptr”在class object中只有一个,而虚表存放的是virtual functions的地址。哦?为什么没有计算static data members?又犯傻了,static member存放在data segment,不存放于class object,当然计算class占用内存大小不需要考虑进去。另外,如果想知道为什么nonstatic、non-virtual function members没有占用内存,狠戳这里。

除了上面阐述的简单模型外,alignment(对齐)不可忽略,需牢记在心。下面正式讨论Data Member布局。


二、Data Member布局

在预热这一小节中,其实讨论了大部分class data members在内存中的存储,这里简单介绍,data member在内存中是如何排列(即布局)的。以下面的class为例:

class Point3d    {    public:        // ...    private:        float x;        static list<Point3d*> *freeList;        float y;        static const int chunkSize = 250;        float z;    };

经过第一小节的分析,该Point3d class object布局中仅有x,y和z。C++Standard要求,同一access section(也就是private、public、protected等区段)中,members的排列只需符合“较晚出现的members在class object中有较高的地址”这一条件即可。也就是说,各个members并不一定连续排列。什么东西可能会介于被声明的members之间呢?members的边界调整(alignment)可能就需要填补一些bytes,也可能是编译器合成的东西(比如:vptr),vptr传统上被放在所有显式声明的members的最后,不过如今也有一些编译器把vptr放在一个class object的最前端。

参考文献:《深度探索C++对象模型》侯捷 译

0 0
原创粉丝点击