【C++】对象模型之Data

基础

数据成员分类

 static data members

  编译器把static data members放在类的对象之外,即将唯一的实体在程序数据区中,当两个类中的static data members同名时,编译器会推导出独一无二的名字。

  我们可以通过对象、指针、和类都可以取得static data members。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class A{
 6 public:   
 7     static int stcMem;
 8     int i = 10;
 9 };
10 
11 int A::stcMem = 5;   //初始化
12 int main()
13 {
14     A a;
15     A* p = &a;
16     cout << a.stcMem << endl; //通过对象取用
17     cout << p->stcMem << endl; //通过指针取用
18     cout << A::stcMem << endl; //通过类取用
19 
20     return 0;
21 }
22 
23     

 nonstatic data members

  编译器将nonstatic data members整合在一起为类对象实体,C++并没有规定对象的nonstatic data member的布局顺序,顺需由不同的编译器自己决定。当我们取用nonstatic data members时,编译器会根据对象地址和成员偏移量来确定。

  我们可以通过对象、指针、引用、和成员函数中的this指针取用nonstatic data members。

对象的内存布局

 单继承

   

  不要多态,即没有虚函数的情况:

 

  加上多态:

 

 多继承

  

 虚继承

 

 对象大小

  一个class对象需要多少内存呢,一般是一下几点的和:

  • nonstatic数据成员的大小之和;
  • 加上由于对齐而产生的填补(与机器有关);
  • 加上为了支持virtual而增加的额外负担(与编译器有关 )。

   另外值得注意的是一个没有nonstatic的类的对象的大小是1,这是被编译器安插的一个char类型,为了让该类的每个对象具有独一无二的内存地址。

指向data members的指针

  作用1:可以用来确定vptr是放在对象模型的首部还是尾部。不同的编译器vptr的位置不同,因为C++允许把vptr放在任何位置,通常会放在首部和尾部。

  作用2:可以用来确定对象成员的布局次序

  &className::dataName 可以获得成员数据的对象中的偏移量,注意这个偏移量会被编译器加1,为了可以表示空数据类的成员指针。所以在取用对象的时候,&obj + (&className::dataName - 1)

参考

  《深度探索C++对象模型》

 

 

 

原文地址:https://www.cnblogs.com/chen-cs/p/13091686.html