深入探索C++对象模型-1
概述
在实际生产中,遇到一个复杂的类,如果能看出这个类的内存模型结构,那么以后的操作基本就没有难度的;
所以说,学会分析一个类的内存模型,是每一个C++程序员必须要会的知识。
下面,就让我们来了解C++对象模型!
C++类封装和C中的结构体的区别
C++的类封装是在C语言中的结构体的基础上构建起来的,C结构体只允许存在数据,而不会存在对数据的操作。
C++语言中延承C语言中的结构体,但增加的对数据的操作,即成员函数;
类是对结构体的进一步封装,使某些数据成员对外不可见,称为私有成员。
类和结构体最大的区别就是:结构体成员均是public类型的。
那么,类和结构体的布局成本有没有区别呢?
对于只有数据成员的类和结构体在内存的布局是相同的,没有增加成本。
而members functions 虽然含在class的声明之内,却不出现在object之中。每一个 non-inline member fuction 只会诞生一个函数实体,调用时链接至函数体。至于每一个"拥有零个或一个定义"的 inline function 则会在其每一个调用者(模块)身上产生一个函数实体。
在C++中,有两种 class data members: static 和 nonstatic,以及三种 class member functions : static、nonstatic 和 virtual。
在C++对象模型中,非静态数据成员被配置在每一个 class object 之内,静态数据成员则被存在个别的 class object 之外,静态和非静态的成员函数也被放在个别的 class object 之外。
C++在布局及存取时间上主要的额外负担是由 virtual 引起。包括:
- virtual function 机制:用以支持一个有效率的"执行期绑定"
- virtual base class 用以实现"多次出现在集成体系中的base class,有一个单一而被共享的实体。
虚函数以及虚函数表
虚拟函数的实现
1.每一个 class 产生一堆指向虚函数的指针,放在表格之中,这个表格被称为 virtual table(vtbl);
2.每一个 class object 被安插一个指针,指向相关的 virtual table。这个指针通常被称为 vptr。vptr 的设定和重置都由每一个类的构造函数、析构函数和赋值操作符重载函数自动完成且一旦完成初始化不能修 改。每一个类所关联的type_info object(主要用于RTTI)也经由 virtual table被指出来,通常放在表格的第一个slot。
多重继承模型
C++最初采用的继承模型时间基类对象中的数据成员直接存放在继承类对象内存中,包括基类对象的虚函数表和虚指针(貌似现在也是这样的模型),这样就可以对基类成员进行最有效率的存取,然而缺点是如果基类成员有任何的修改将会导致基类对象和继承类对象的重新编译。
有人提出一种间接存取模型:在继承类对象中放置一指针Bptr,该指针指向继承类的基类表,类似与虚函数表,基类表中每一项都指向继承类对象的基类 对象。这样的好处是,基类对象的任何改变吗都不会影响到继承类对象的内存布局,缺点是导致对基类对象成员的存取效率低,随着继承深度的增加,间接性越强, 效率越低。
因此又有人提出,在继承类对象中放置与基类相等数目的指针指向每个基类,这样存取时间就恒久不变了,但是这样无疑增加了继承类的内存开销。
目前使用的多重继承模型仍为第一种,继承类对象中含有所有基类对象数据成员和虚指针,同时继承基类的虚函数表共享为继承类的虚函数表。
虚拟继承模型
虚拟继承保证继承类中只含有一个基类对象,继承类中会产生虚指针指向虚表中offset指向继承类中的基类对象。只有直接虚继承的继承类对象才会产生Vptr。
目前,关于虚拟继承的继承类的内存布局有三种模型:
1、原始模型:在每个继承类对象中设置指针,用以指向继承类中的基类对象。优点:通过指针能够保证继承类中只有一个基类对象,可以直接存取基类对象。缺点:若继承类有多个虚拟基类,则需要多个指针指向基类们,会消耗较多的内存。
2、有人提出像虚函数表一样,提供一个虚拟基类表virtual base class table,表中每个slot指向一个基类对象的地址。在继承类对象中,设置一个虚拟基类表指针指向基类表。优点:继承类减少了因虚拟基类指针而产生的开 销,且继承类不会因为虚拟基类的增加而改变内存模型。缺点:存取基类对象数据成员会导致效率低下。
3、现在最常用的模型:扩充原Virtual table,在虚表负offset位置指向虚基类对象,因此,只要是虚继承就会产生虚指针和虚表。
虚拟多继承,采用“钻石”继承结构,其每个类的内存分布如下图:其中虚指针的位置可以在顶部或尾部。
上述内容是类对象内存模型的介绍:
(1)无虚函数和虚继承:nostatic数据成员存放在对象中,static数据成员存放在对象外属于整个类。nostatic和static函数成员均放在对象外。
(2)有虚函数和虚继承:virtual函数放在虚函数表中,通过虚指针进行查找调用。基类对象数据成员和虚指针均存放在继承类的对象中。
深入探索C++对象模型-1的更多相关文章
- 读书笔记《深度探索c++对象模型》 概述
<深度探索c++对象模型>这本书是我工作一段时间后想更深入了解C++的底层实现知识,如内存布局.模型.内存大小.继承.虚函数表等而阅读的:此外在很多面试或者工作中,对底层的知识的足够了解也 ...
- 柔性数组-读《深度探索C++对象模型》有感 (转载)
最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下 ...
- 柔性数组-读《深度探索C++对象模型》有感
最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下 ...
- [读书系列] 深度探索C++对象模型 初读
2012年底-2014年初这段时间主要用C++做手游开发,时隔3年,重新拿起<深度探索C++对象模型>这本书,感觉生疏了很多,如果按前阵子的生疏度来说,现在不借助Visual Studio ...
- 拾遗与填坑《深度探索C++对象模型》3.3节
<深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...
- 拾遗与填坑《深度探索C++对象模型》3.2节
<深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...
- 深度探索C++对象模型
深度探索C++对象模型 什么是C++对象模型: 语言中直接支持面向对象程序设计的部分. 对于各个支持的底层实现机制. 抽象性与实际性之间找出平衡点, 需要知识, 经验以及许多思考. 导读 这本书是C+ ...
- 《深度探索C++对象模型》读书笔记(一)
前言 今年中下旬就要找工作了,我计划从现在就开始准备一些面试中会问到的基础知识,包括C++.操作系统.计算机网络.算法和数据结构等.C++就先从这本<深度探索C++对象模型>开始.不同于& ...
- C++的黑科技(深入探索C++对象模型)
周二面了腾讯,之前只投了TST内推,貌似就是TST面试了 其中有一个问题,“如何产生一个不能被继承的类”,这道题我反反复复只想到,将父类的构造函数私有,让子类不能调用,最后归结出一个单例模式,但面试官 ...
- 深入探索C++对象模型(一)
再读<深入探索C++对象模型>笔记. 关于对象 C++在加入封装后(只含有数据成员和普通成员函数)的布局成本增加了多少? 答案是并没有增加布局成本.就像C struct一样,memeber ...
随机推荐
- Ajax基础--JavaScript实现
ajax原理 1.ajax 即“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),也就是无刷新数据读取. 通俗地讲就是:AJAX 通过在后台与 ...
- CHROME下载地址
Chrome官方独立中文安装包下载地址 一般我们安装Google Chrome浏览器都是访问 http://www.google.com/chrome/?hl=zh-CN 然后下载运行ChromeSe ...
- sql新增后返回主键
对于刚学的人来说有点帮助,新增后返回主键有两种方法: 1,返回自增的主键: INSERT INTO 表名 (字段名1,字段名2,字段名3,…) VALUES (值1,值2,值3,…) SELECT @ ...
- 在 LINQ to Entities 查询中无法构造实体或复杂类型
public List<CustomerType> GetCustomerTypesBySchemaTypeCode(int schemaTypeCode) { var query = ( ...
- Java 中 Comparable 和 Comparator 比较(转)
转自http://www.cnblogs.com/skywang12345/p/3324788.html 本文,先介绍Comparable 和Comparator两个接口,以及它们的差异:接着,通过示 ...
- 3ds max 2016 新功能
3ds max 2016 新功能_MCG节点编辑器 这是介绍视频下载: http://pan.baidu.com/s/1gds4wqJ
- [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】
题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...
- 整理的Java资源
这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化的方式 ...
- Java中的属性与字段的区别
Java中属性和字段的区别 Java中的属性,通常可以理解为其属名性时根据get和set方法名得出的. 其规则是:去掉get或set后其剩余的字符串,如果第二个字母是小写的,则把第一个字母也变成小写 ...
- Oracle三组难缠的hint no_unnest/unnest,push_subq,push_pred--平展化(转)
经常有人把这三个hint搞混,主如果因为对三种重写道理不清楚.特总结如下.(实验景象为10204)1. no_unnest, unnestunnest我们称为对子查询展开,顾名思义,就是别让子查询孤单 ...