读《深度探索C++对象模型》之分层继承对于内存布局的影响

请看以下代码:

class Concrete
{
public:
private:
	int val;
	char c1;
	char c2;
	char c3;
};

我在我的电脑上运行,求得的类Concrete的大小为8byte,我想还是符合我们的预期(val:4byte, c1 : 1byte, c2 : 1byte, c3: 1byte),在加上字节对齐的一个字节,刚好是8byte。

那如果我为了酷炫,改成以下的继承方式,对于空间会有什么影响呢。

class Concrete1
{
public:
private:
	int val;
	char c1;
};

class Concrete2 : public Concrete1
{
public:
private:
	char c2;
};

class Concrete3 : public Concrete2
{
private:
	char c3;
};

那么求得的空间大小又是如何呢。

竟然是上面的2倍。那么为什么是这样呢。

因为C++标准规定:

出现在继承类中的基类对象有其完整性。

那么我们分析一下,Concrete1的对象,其内含两个数据成员:val 和c1,加起来是5byte,加上字节对齐是8byte。

Concrete2 加上Concrete1的数据,再加上1byte,刚好是8+1=9byte,加上字节对齐是12byte.

Concrete3加上Concrete2的对象再加上1byte,刚好是12+1=13byte,加上字节对齐是16byte。

那为什么我们在Concrete2和Concrete3的1byte不加到Concrete1对象上呢。

正是为了满足C++的保证。

我们举个例子来说明,

假如有以下代码:

	Concrete2 *p2 = new Concrete2;
	Concrete1 *p1 = p2;

将p2的对象赋给p1,理论上来说,是执行的memberwise的赋值操作(拷贝),那么如果我们的Concrete2的1byte对象跟Concrete1的对象绑定在一起,就是填充到Concrete1对齐的3个字节上,那么p1的数据也包含Concrete2的1byte,那么这样就错了。

时间: 2024-11-05 13:15:06

读《深度探索C++对象模型》之分层继承对于内存布局的影响的相关文章

[读书系列] 深度探索C++对象模型 初读

2012年底-2014年初这段时间主要用C++做手游开发,时隔3年,重新拿起<深度探索C++对象模型>这本书,感觉生疏了很多,如果按前阵子的生疏度来说,现在不借助Visual Studio之类的工具的话,写C++代码感觉要比较费劲,最近重读了这本书后,感觉要写点东西下来(因为懒得用笔作笔记,太慢了-_-!)加深下印象. 以前还是新手的时候,总是认为: 1.class如果没有定义任何constructor的话,编译器会自动合成一个default constructor(我习惯叫缺省的构造函数)出

柔性数组-读《深度探索C++对象模型》有感 (转载)

最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下: 例如,把单一元素的数组放在一个struct的尾端,于是每个struct objects可以拥有可变大小的数组.    code: struct mumble { //stuff char pc[1];    };        //从档案或标准输入装置中取得一个字符串,然后为struct本身和该字符串配置

深度探索C++对象模型的读书心得

参考:深度探索C++对象模型 (stanley B.Lippman著 侯捷翻译) 1. Page9 : C++对象模型,说明每一个类仅有一个虚函数表Vtbl,而类的每一个对象都有指向其表的指针. 2. Page30:引用也需要与一个指针(大小为4BYTE)相同的空间. 3. Page28: 指针类型会教导编译器如何解释某个特定地址中的内存内容及大小. 4. Page39: explicit关键字能够制止"单一参数的constructor被当做一个Conversion运算符" 5. Pa

【深度探索C++对象模型】第二章 构造函数语意学(上)

第二章 构造函数语意学(The Semantics of Constructors) -- 本书作者:Stanley B.Lippman 一.前言 首先让我们来梳理一个概念: 默认构造函数(Default Constructor) : 是在没有显示提供初始化式时调用的构造函数.它由不带任何参数的构造函数,或是为所有形参提供默认实参的构造函数定义.如果定义的某个类的成员变量没有提供显示的初始化式时,就会调用默认构造函数(Default Contructor). 如果用户的类里面,没有显示的定义任何

《深度探索c++对象模型》chapter1关于对象对象模型

在c++中,有2种class data member:static和nostatic,以及3钟class member function:static,nostatic和virtual.已知下面这个class Point声明: class Point { public: Point(float xval); virtual ~Point(); float x() const; static int PointCount(); protected: virtual ostream& print(o

【深度探索c++对象模型】Function语义学之虚函数

虚函数的一般实现模型:每一个class有一个virtual table,内含该class之中有作用的virtual function的地址,然后每个object有一个vptr,指向virtual table. 识别class是否支持多态,唯一恰当的方法是看它是否有virtual function,只要class拥有virtual function,它就需要额外的执行期信息. 考虑ptr->z(),ptr是基类指针,z是虚函数,为了找到并调用z()的适当实体,我们需要两项信息: 1.ptr所指对象

《深度探索c++对象模型》chapter3 Data语意学

一个空的class:如 class X{} ; sizeof(X)==1; sizeof为什么为1,他有一个隐晦的1 byte,那是被编译器安插进去的一个char,这使得class2的两个objects得以在内存中配置独一无二的地址: X a,b; if(&a==&b) cerr<<"yipes!"<<endl; class X{}; class Y:public virtual X{}; class Z:public virtual X{};

深度探索C++对象模型

著:Stanley B. Lippman  侯捷译  Inside the C++ Object Model 第一章:关于对象(Object Lessons) C++对象模型,了解到也是一个演变的过程,C++对象中包含了以下内容:(data members) non-static data,static data(const),以及(member functions):static,non-static,virtual 发展的主要过程主要集中于如何存储data 和 function,寻求时间和空

深度探索C++对象模型 第三章 Data 语意学

一个有趣的问题:下列 类 sizeof大小 class X{}    //1 class Y:public virtual X{} //4 or 8 class Z:public virtual X{} // 4 or 8 class A:public Y,public Z{} // 8 or 12 主要原因:为了保持每一个类生成对象在内存中的唯一性,编译器必须要给空类生成一个char来维持object的唯一性: 而virtual继承中,仅保持了base class的指针,有些编译器会继承bas