3.2 数据成员的布局

class Point3d
{
public:
    //...
private:
    float _x;
    static List<Point3d*> *freeList;
    float _y;
    static const int chunkSize = 250;
    float _z;
};

nonstatic data members 在 class object 中的排列顺序和其被声明的顺序是一致的。 任何 static data members 都不会被放进对象布局之中。static data members 都存放在程序的 data segment 中,和 class objects 无关。
C++ Standard 要求, 在同一个 access section (即 private, public, protected 等) 中,members 的排列只需符合较晚出现的 members 在 class object 中有着较高的地址这一条件即可。 也就是说,各个 members 并不一定要连续排列(意味着中间可被其他区段分隔)。那么有什么会可能被插在中间呢? 为了对齐所填补的 bytes。
编译器可能会合成一些内部使用的 data members,以支持整个对象模型,vptr 就是这样的东西, 当前所有编译器都把它安插在每一个内含 virtual function 的 class object 之内。vptr 传统上被放在所有声明的 members 的最后, 有的编译器也把 class object 的最前端。 因为 C++ standard 秉承先前所说的“对于布局放任的态度”, 所以允许编译器对内部产生的 members 放在任何位置上, 甚至放在那些被程序员声明的 members 之间。
当然, 既然是放任的态度, C++ standard 也允许编译器将多个 access sections 之中的 data members 自由排列, 不必在乎它们出现在 class 声明中的次序, 意味着形如:

class Point3d
{
public:
    //...
private:
    float _x;
private:
    float _y;
private:
    float _z;
};

大小不改变, 而实际在编译器中,编译器可以随意把 y 或 z 或什么其他东西放为第一个, 但目前的编译器没有这么做的。(sections之间无序,section内部有序)
编译器实际的处理都是把一个以上的 access section 连锁在一起, 依照声明的次序连成一个连续区块。 Access section 的多少不会引起编译器的额外负担,不管是在多个 sections 中 声明多个 members, 还是在一个 section 中声明全部的 members, object 的大小都是一样的。

//接受两个 data members, 判断谁先出现在 class object 之中。
//如果两个 members 都是不同的 access sections 中的第一个被声明的
//此函数就可以判断哪一个 section 先出现
template< class class_type, class data_type1, class data_type2 >
char* access_order(data_type1 class_type::*mem1, data_type2 class_type::*mem2)
{
    assert(mem1 != mem2);
    return mem1 < mem2 ? "member 1 occurs first" : "member 2 occurs first";
}
posted @ 2021-04-18 11:47  点|滴  阅读(4)  评论(0)    收藏  举报