zoukankan      html  css  js  c++  java
  • Data Member 的布局

    考察以下代码:

    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 mambers, 以支持整个对象模型, 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;
        static List<Point3d*> *freeList;
    private:
        float _y;
        static const int chunkSize = 250;
    private:
        float _z;
    };

    实际上与前一段代的大小和组成是一样的, 我的理解就是, 只要你是搞革命的, 我们不管你是从哪来的。 而实际在编译器中, 编译器可以随意把 y 或 z 或什么其他东西放为第一个, 但似乎目前的编译器没人这么做。
    编译器实际的处理都是把一个以上的 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";
    }

    上述函数可以这样被调用:
    access_order( &Point3d::_z, &Point3d::_y );
    PS: 但是, 我在 vs2013 上运行这段代码没有成功, 显示的错误是 error C2296: “<”: 非法,左操作数包含“int Point3d::* ”类型
    这就让人不淡定了, 希望如果有人看到这篇博客可以指点一二, 我先在这谢谢了!

  • 相关阅读:
    AddParent
    AddChild
    贝塞尔曲线代码
    顶点纹理shader
    抽象方法与抽象类
    Application类
    布局组件
    C#单例和Unity单例
    Unity&UGUI
    Json解析
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4106772.html
Copyright © 2011-2022 走看看