分享
 
 
 

C++对象模型之三 数据成员笔记

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

C++对象模型之三 数据成员笔记

首先纠正第一章中关于静态成员在对象之外,对象用指针连接,实际上对象没有用指针去连接他们,而是通过类存取的. 下面是空类的虚继承.

Class x {};

class y :public virtual x{};

lass z:public virtual x{};

class A: public y,public z {};

其大小是 X =1 Y=4 Z=4 A=8;虚继承基类 X 隐藏1字节字符使的类两个对象在内存中有不同的地址。

数据成员的布局

非静态数据成员在类对象中的排列顺序和其被声明的顺序一样,任何中间介入的静态数据成员都不会放进去。在同一个存取节中各个成员并不一定连续排列,符合较晚出现的成员在类对象中有较高的地址。编译器可能合成些内部使用的数据成员以支持整个对象模型。编译器把多个相同的存取节合并在一起。

数据成员的存取

1 静态数据成员:在对象之外,并做为全局变量看,每一个对象的存取许可及类的关联并不会导致空间和时间的负担。

Point3d origin, *pt=&origin;

Origin.chunSize=250;

Pt->chunSize=250;

被内部转化为:

Point3d::chunkSize=250; Point3d::chunkSize=250; 无论是对象还是指针都一样。

如果静态数据成员经函数调用:foobar ( ).chunkSize=250; 被转化为:(void) foobar(); Point3d::chunkSize=250;

取一个静态数据成员的地址,得到的是指向该数据类型的指针,而不是一个指向其类成员的指针。

&Point3d::chunkSize; è const int *

2 非静态数据存取

欲要对非静态数据存取,编译器需要把类对象的起始地址加上数据成员的偏移量。

Origin.y=0.9; è &Origin+(&Point3d::y-1);

虚继承比其它方式存取数据成员会比较慢点。用对象和指针存取虚继承而来的数据成员时指针存取操作必须延迟到执行期,而对象在编译期就固定了。

继承与数据成员

在C++模型中派生类对象所表现出来的东西,是自己的成员们加上其基类们的成员的总和,基类成员总是先出现,但是虚继承类除外。

1 单继承: 类Point3d单继承于Point2d

2 单继承含虚函数:Point3d单继承于Point2d,Point2d有virtual void foobar();

3 多继承:Point3d继承于Point2d; Vertex3d 多继承于 Point3d 和Vertex

4虚继承:Point3d virtual Point2d ; Vertex :virtual Point2d; Vertex3d:public Point3d,public Vertex;

1 每个对象会多一个指针指向虚继承基类 (Point2d);

2 每次继承时存取时间会增加,因为要调整一些指针;

所以有两种对象模型:一种就是增加指针继承时调整指针;另一种是把虚继承基类的偏移地址放在虚函数表第一位值。

对象成员的效率

我使用BCB5 在塞扬A466 128SDRAM 下

void __fastcall TForm1::Button1Click(TObject *Sender)

{ //单个变量

float pA_x,pB_x,pA_y,pB_y,pA_z,pB_z;

pA_x=1.725;pA_y=0.875;pA_z=0.478;pB_x=0.315;pB_y=0.317;pB_z=0.838;

long StartTime=GetTickCount();

for(int i=0;i<10000000;i++)

{

pB_x=pA_x-pB_z;

pB_y=pA_y+pB_x;

pB_z=pA_z+pB_y;

}

long EndTime=GetTickCount();

Label1->Caption=EndTime-StartTime;

}

void __fastcall TForm1::Button2Click(TObject *Sender)

{

class Point3d

{

public:

Point3d(float xx=1.725,float yy=0.838,float zz=0.315): _x(xx),_y(yy),_z(zz){}

float & x() {return _x;}

float & y() {return _y;}

float & z() {return _z;}

private:

float _x,_y,_z;

};

Point3d A,B;

long StartTime=GetTickCount();

for(int i=0; i<10000000;i++)

{

B.x()=A.x()-B.z();

B.y()=A.y()+B.x();

B.z()=A.z()+B.y();

}

long EndTime=GetTickCount();

Label2->Caption=EndTime-StartTime;

}

剩余的代码没有给出,大家自己可以做做,对象不会很慢,纳闷结构体比单个变量快?

未优化

优化

单个变量

0.530 (秒)

0.521 (秒)

结构体

0.260 (秒)

0.200 (秒)

数组

0.531 (秒)

0.521 (秒)

对象

2.083 (秒)

0.521 (秒)

书上还做了各种继承的测试结论:

1 关闭优化后内联函数存取比较慢,所以程序员应该实际测试下,不要光凭推理或常识判断。

2 有时侯优化操作并不一定总是有效运行。

3 虚继承在优化后同样效率令人失望。

指向数据成员的指针

class Point3d

{

public:

virtual ~Point3d();

protected:

static Point3d origin;

float x,y,z;

};

因为 vptr 占4个字节 float 占4个字节 所以 vptr放在头部三个数据成员的偏移量是 4,8,12;vptr在尾部0,4,8。

如果你取数据成员的地址 &Point3d::x 返回的总是多1个字节,为什么?

因为

float Point3d::*p1=0;

float Point3d::*p2=&Point3d::x;

if (p1==p2) //无法区分 所以不得不加上1个字节

而 &Point3d::x; 和 &origin.Z 是不同的 前者得到的是在类中的偏移量,后者得到是真正的内存地址。

指向成员的指针效率

未优化

优化

直接存取

1.42

0.8

指针指向已绑定的成员

3.04

0.8

指针指向已数据成员

5.34

0.8

指向数据成员的指针

未优化

优化

没有继承

5.34

0.8

单一继承(三层)

5.34

0.8

虚继承(一层)

5.44

1.6

虚继承(二层)

5.51

2.14

虚继承它妨碍了优化,每一层中导入了额外的层次间接性

pB.*bx 转化为 &pB->__vbtr+(bx-1) 而不是 &pB+(bx-1)

作者名:曾凡坤, 又名曾牧暗鲨,网名:大白鲨 2003-7-29

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有