C++对象模型-Data语义学 第三章笔记

读完C++对象模型书后,做一个笔记整理
第一章-关于对象
第二章-构造函数语义学
第三章-Data语义学
第四章-Function语义学
第五章-构造拷贝解析语义学
第六章-执行期语义学
第七章-在对象模型的尖端

class A; class B:public virtual A; class C: public virtual A; class D: public B,public C此种情况下一般 A的大小为1,sizeof(B)=sizeof©=8;因为B,C中包含指向虚基类的一个指针。sizeof(D)为12,因为A中一字节+B中一个指针+C中一个指针=9,由于需要内存对齐的原因会padding至12。
若编译器处理了empty virtual base class 则A中不会有1字节的插入占位。上述计算就会相应减少尺寸及padding.

每个class的大小可能比预期的要大,主要因为 1编译器加上额外的data members用于支持某些语言特性,主要是virtual 2由于alignment的需要

  1. 成员的绑定
    始终把nested type 声明放在class起始处,以便在class中引用到该类型时可以正确resolve
typedef int mytype;
class A
{
public:
    // 如果要正确relove为float需要在第一次使用mytype之前声明
    // typedef float mytype;
    void func(mytype x) { m_x = x;}// 注意此处的mytype会被识别为int,因为到这行还未出现后续的typedef float mytype
private:
    typedef float mytype;
    mytype m_x;
};
  1. data member的布局
  • static成员放在程序的data segment中,不会与object中的成员混在一起。
  • c++只要求在同一access session中的成员后出现的排在后面,不要求连续排列
  1. data member的存取
  • static成员的存取,由obj.x 和 pt->x两种方式完全相同。因为static成员存放于data segment中,与object并无关系。对它的访问转化为一个地址访问。且编译器会将static成员名字进行name mangling(名字修饰)以避免data segment中的重名。
  • nonstatic成员存取时必须经由一个object,在成员函数中的存取暗含了this指针。(this->)x = other->x; nonstatic成员的偏移量在编译期即可得知。
  • 而若类是派生自虚基类时,obj.x 和 pt->x 会有较大差异,因为pt指向的类型不能确定,必须于执行期才经由额外的操作才能决定。而obj类型确定,存取不会有问题。
  1. 继承与data member
  • 在单继承中C++会保持base class subobject在derived class中的原样完整性。
class A
{
	int m_a;
	char m_c;
}// sizeof A为8 含3字节padding

class B:public A
{
    char m_b;
}// 此时sizeof B 为12 ,A中的padding保留,m_b排在其后。
// A* pa1 = A* pa2 = new A();
// pa2 = new B();
// *pa1 = *pa2; // 上述设计保证了这一行能正确,不会在m_c后设置预期之外的值
  • 加入虚函数后内存内会多一个vptr来指向相应vtbl
  • 在多重继承时,其问题主要发生在子类与其第二或之后父类间的指针相互转换,需要加或减中间的base class object 大小,第一父类与子类指向相同地址,故无问题。
  • 引入虚继承后,有多种方案可以实现存取虚基类的成员,但均由于其复杂,而不推荐。最好的使用方法是一个virtual base class其中没有任何data members。
  1. 成员的效率
  • 需要经过实测才能确定我们所谓的优化是否有效
  1. 指向data members 的指针
  • &Class::x 返回的是x在对象中的偏移,在VC中为原始偏移值,其它编译器中可能+1后的值。请注意以下代码。
int Class::* p1 = 0;
int Class::* p2 = &Class::m_x;
if (p1 == p2)// 为了这里能正常判断,有些编译器选择p2初始化时用偏移+1,而VC是给p1赋值0xffffffff
    cout << "p1=p2" << endl;
  • &obj.x 返回x在内存中的实际地址

下一篇 第四章-Function语义学

你可能感兴趣的:(C++,c++)