深度探索C++对象模型之第三章:data语义学中对象布局

说明: 看到  http://www.roading.org/?p=545 已经整理的很好了,所以前部分大部分引用原文,感谢原作者@~@,后半部分主要引用自书本

类对象占用的内存空间可能比我们想象的要大,有如下原因:

(1) 由编译器自动加上额外的data memebers,用以支持某些语言特性(主要是各种virtual特性)

(2)因为边界调整(alignment)的需要(详细请看:内存对齐的理解

下面给出个实例:

class X{};
class Y:virtual public X{};
class Z:virtual public X{};
class A:public Y, public Z{};


以上实例中

Lippman的一个法国读者的结果是:                      vs2008/2010上的结果是:

sizeof X yielded 1                                              sizeof X yielded  1 
sizeof Y yielded 8                                              sizeof Y yielded   4  
sizeof Z yielded 8                                              sizeof Z yielded  4 
sizeof A yielded 12                                            sizeof A yielded  8

(下面要对这两个不同的结果进行分析)

对于像X这样的一个的空类,编译器会对其动点手脚——隐晦的插入一个字节。 为什么要这样做呢? 插入了这一个字节,那么X的每一个对象都将有一个独一无二的地址。如果不插入这一个字节 那对X的对象取地址的结果是什么?两个不同的X对象间地址的比较怎么办?

我们再来看Y和Z。首先我们要明白的是实现虚继承,将要带来一些额外的负担——额外需要一个某种形式的指针。到目前为止,对于一个32位的机器来说Y、Z的大小应该为5,而不是8或者4。我们需要再考虑两点因素:alignment和编译器的优化。

我们再来看Y和Z。首先我们要明白的是实现虚继承,将要带来一些额外的负担——额外需要一个某种形式的指针。到目前为止,对于一个32位的机器来说Y、Z的大小应该为5,而不是8或者4。我们需要再考虑两点因素:alignment和编译器的优化。

alignment(内存对齐的理解)会将数值调整到某数的整数倍,32位计算机上位4bytes(32位)。内存对齐可以使得总线的运输量达到最高效率。所以Y、Z的大小被补齐到8就不足为奇了。

那么在vs2010中为什么Y、Z的大小是4而不是8呢?我们先思考一个问题,X之所以被插入1字节是因为本身为空,需要这一个字节为其在内存中给它占领一个独一无二的地址。但是当这一字节被继承到Y、Z后呢?它已经完全失去了它存在的意义,为什么?因为Y、Z各自拥有一个虚基类指针,它们的大小不是0。既然这一字节在Y、Z中毫无意义,那么就没必要留着。也就是说vs2010对它们进行了优化,优化的结果是去掉了那一个字节,而Lippman的法国读者的编译器显然没有做到这一点。

当我们现在再来看A的时候,一切就不是问题了。对于那位Lippman的法国读者来说,A的大小是共享的X实体1字节,X和Y的大小分别减去虚基类带来的内存空间,都是4。A的总计大小为9,alignment以后就是12了。而对于vs2010来说,那个一字节被优化后,A的大小为8,也不需再进行alignment操作。

 

下面讲下类中存在数据成员和继承关系时类对象中的内存分配:

假设有如下三个类:

class Concrete1
{
 public:
	//....
 private:
	int val;
	char bit1;

};
class Concrete2 : public Concrete1
{
 public:
	//....
 private:
	char bit2;
};
class Concrete3 : public Concrete2
{
 public:
	//...
 private:
	char bit3;
};

以32为机器为例,在上述类中:

(1)Concrete1内含两个members: val 和bit1, 加起来是5个字节。边界对齐填充后Concrete1对象实际占用8个字节.

(2)很多人错误的认为Concrete2只加了一个char类型,大小为5+1 + 3(边界对齐) = 8个字节。 其实Concrete2 占用了12个字节。即Concrete1的填充空间仍然存在 8 + 1 = 9 根据边界对齐,再加上3个字节。 Concrete2 占用了12个字节。

(3)相同的道理Concrete3 对象占用16字节

以上中Concrete2其实是浪费6个字节来填补空间。Concrete3浪费12个字节来填补空间。
以下面一组图来说明这三个类的对象布局:

原因下载还没有看明白,等明白后再续在原书:P106



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值