文章目录

  • 前言
  • 思维导图
  • 第一章 关于对象
  • 第二章 构造函数语意学
    • 构造函数
    • 拷贝构造函数
    • 初始化列表
  • 第三章 Data 语意学
  • 第四章 Function 语意学
    • 非静态成员函数
    • 静态成员函数
    • 虚成员函数
  • 第五章 构造、析构、拷贝语意学
  • RTTI
  • 模板函数的实现逻辑

前言

俗话说得好,好记性不如烂笔头,本文主要是重温了一下经典书籍《深度探索C++对象模型》,然后一些内容摘录,主要记录的是我自己的精简版,建议读者有相关的知识需要还是慢慢去啃一下原书比较好。

思维导图

第一章 关于对象

首先介绍了 C++ 类的情况, C++类的内存存储方式是:只包含非静态成员变量的大小,成员函数(静态,非静态),静态成员变量都是单独存储的;有虚函数的则在内存中多一个虚函数表。

第二章 构造函数语意学

一般都会认为编译器会自动生成一些我们需要的构造函数,包括构造函数,析构函数,拷贝构造函数,赋值构造函数等。并且一般编译器自动生成的都是叫做 trival 的,这个主要是为了满足编译器自己的需求,而不是为了满足程序员的要求,所以程序变量没有初始化之类的,编译器也不会自动帮你初始化的,因为这是程序员的任务!

只有下面4种情况下才会真正的去合成相关的构造函数,并且是 nontrival 的否则很多是不会生成的。

构造函数
  1. 带有其他 default 构造的类成员对象
  2. 带有 default 构造基类的子类
  3. class 声明/继承里有虚函数
  4. 继承链里有虚继承

以上 4 种情况只有是在处理,带有或者继承有默认构造函数的类对象,因为要调用它们的初始化函数初始化它们。其次就是处理虚函数表。

拷贝构造函数

基本也是同构造函数的 4 种情况。

  1. 当 class 内带有其他声明有一个 copy constructor 时,不论是显式声明还是被编译器合成
  2. 当 class 继承自一个 base class 而其存在一个copy constructor 时
  3. 当 class 声明一个或对个虚函数时
  4. 当 calss 派生自一个继承链,其中有一个或多个虚基类时

前两种就还是编译器需要将 member 或者 base class 的拷贝构造函数安插到被合成的拷贝构造中,后面两种主要还是要处理好虚函数表的位置,而不就是简单的 copy 。

初始化列表

必须使用初始化列表的情况:

  1. 初始化一个引用对象时
  2. 初始化一个常量成员时
  3. 调用一个基类的构造函数,它有一组参数
  4. 调用一个类成员的构造函数,它有一组参数

1,2 点因为进入构造函数体内时,实际上变量都已经初始化完毕了,引用和 const 都是一旦初始化就不可改变的,构造函数能做的只有赋值,而 const 和 引用类型是不可以赋值的。

3,4 则是可能从效率部分考虑,不用初始化列表赋值,构造函数有参数的情况下,编译器会自动编程,生成一个临时对象,然后拷贝构造,然后析构临时对象;初始化列表则直接调用相关的构造函数了。

  • 初始化列表顺序与成员声明顺序一致
  • 初始化列表执行在构造函数之前

第三章 Data 语意学

  1. 空的类会有一个 bit 大小,使它的对象可以在内存中被分配一个独一无二的地址。
  2. non static data members 在类对象中的排列顺序和其被声明的顺序一致
  3. 编译器会在 name-mangling 来解决命名冲突的问题
  4. Static data member 存在 class 之外,所以可以直接访问,而 non static 直接放在每个类内,所以要有类对象来存取,直接存取由 this 指针来完成,由偏移位置 offset 来访问所有的对象,编译器就可知。
  5. 继承对象的 member 访问,多态可能运行期才确定,所以引用和指针在这个时候效率还是有差距的。
  6. 直接继承并不会增加空间/存取时间上的额外负担, base_calss = derive_class 对象赋值会发生切割。
  7. 单一继承 + 虚函数: 会有很多额外负担,多一个虚函数表也会继承下去
  8. 多重继承也是分别内存叠加,包括相关的虚函数表
  9. 虚继承是父类就只有一份,子类都指向同一块地方,多了一个指向父类的指针

第四章 Function 语意学

类成员函数分为 3 类:静态类成员函数,非静态类成员函数,虚成员函数。

非静态成员函数

编译器要求至少调用非静态成员函数的效率要跟直接调用一般的函数有一致的效率,所以实际调用编译器会通过 name_mangling 和返回值优化等,将类成员函数转成类似普通函数的形式(类名 + 函数名 + 参数列表 + 字符)

静态成员函数

特别之处是:

  • 静态成员函数存储在类外,所以没有this 指针,因为 this 只能操作非静态类成员变量,所以静态成员函数只能操作静态类成员变量。

  • 不能用 const,vilatile 或者 virtual ,这些关键字的操作前提都是需要 this 指针,例如 const 表示不修改类的成员变量,static 都访问不了普通的类成员变量,何来 const 一说呢,虚函数也需要 this 指针来索引虚函数的位置。

  • 不需要类对象就可以被直接调用,可以称为 callback 函数,直接用在线程函数是。

虚成员函数

C++ 中多态是指“以一个 public base class 的指针(引用)寻址出一个 derived class object” 的意思。

所以实现多态又不能直接让指针上加载多态必要的信息,这些信息是:指针所指的正确类型,低啊用虚函数的地址等。否则效率可想很低。

单一继承虚函数

通过虚函数表来实现,一个 class 只会有一个虚函数表,继承子类再重新实现虚函数,则子类的虚函数表中地址直接替换成子类自己的地址。

多重继承下的虚函数

会继承两个表, this 指针需要调整:

// 基类1的虚函数表
Base1 ->  Base1::~Base1()    ->  Base1::A()->  Base1::B()
// 基类2的虚函数表
Base2 -> Base2::~Base2()-> Base2::A()-> Base2::C()// 子类的虚函数表1,重新实现了虚函数 A
Derived -> Derived::~Derived-> Derived::A()-> Base1::B()-> Derived::D()  // 有新增的默认直接放在第一个表后面// 子类的虚函数表2,重新实现了虚函数 A-> Derived::~Derived-> Derived::A()-> Base2::C()

第五章 构造、析构、拷贝语意学

这部分内容主要就是对第 2 章的进一步具体讲解,主要是继承关系中构造、拷贝、析构函数的一些行为特点,例如当拷贝函数是 trival 时候其实编译器的行为。

后面6, 7两章主要是针对运行期,new delete,包括模板实例化的一些内容介绍,

RTTI

下面记录学习到了之前一直只闻其名,不知其意的名词 RTTI:

后面主要记录的就有一个 RTTI(Runtime Type identification) 执行期类型识别。主要就是虚函数表一般除了存储各个虚函数的地址,开头还有一个 type_info 的数据结构,这个数据结构就是多态时类型推导用的。包括 dynamic_cast 就是会利用这个 type_info 的信息,确认当前的指针是否可以进行转换,不能转换则返回 Nullptr。

模板函数的实现逻辑

编译器并不是把模板生成能处理任意类的函数,其会对函数模板通过具体的类型产生不同的函数,编译器对会函数模板进行两次编译:

  • 第一次是编译其声明,即模板代码本身
  • 在调用的地方,对参数替换后的代码进行再编译

所以一般模板的声明和定义都在头文件里,因为函数模板只有被实例化才是真正的函数,如果头文件中只有声明,没有定义,那么编译器无法实例化该模板,最终导致链接错误。

上面 5,6,7 三章这里就不详细记录了,感兴趣的可以阅读原书。

[读书笔记]《深度探索C++对象模型》相关推荐

  1. 读书笔记 | 墨菲定律

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  2. 读书笔记 | 墨菲定律(一)

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  3. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记

    <洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...

  4. 股神大家了解多少?深度剖析股神巴菲特

    股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...

  5. 2014巴菲特股东大会及巴菲特创业分享

     沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...

  6. 《成为沃伦·巴菲特》笔记与感想

    本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...

  7. 读书笔记002:托尼.巴赞之快速阅读

    读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...

  8. 读书笔记001:托尼.巴赞之开动大脑

    读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...

  9. 读书笔记003:托尼.巴赞之思维导图

    读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...

  10. 产品读书《滚雪球:巴菲特和他的财富人生》

    作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...

最新文章

  1. C++ Primer 读书笔记 (1)
  2. hdu1027 Ignatius and the Princess II (全排列 amp; STL中的神器)
  3. “雏鹰”的最近感想……
  4. Vue 在beaforeCreate时获取data中的数据
  5. linux查看进程和终止进程
  6. 计算机系统建模与仿真论文,计算机模拟 仿真论文.doc
  7. 解决 Chrome 下载不了东西 失败 - 已屏蔽 的问题
  8. CEM计算电磁学 -- Lecture 1 学习笔记 (1) --- 麦克斯韦方程、波动方程
  9. 如何实现电脑端和手机端数据传输与共享
  10. 使用IDEA进行Lua代码调试、自动提示、代码跳转、智能重命名
  11. 2018DeeCamp笔试题目第二套B卷
  12. 轻松制作 Notion 风格的头像 - Notion Avatar Maker
  13. view的superview的变换
  14. html页面打印a4尺寸,html网页打印A4样式
  15. 软件工程毕业设计选题java_2021年计算机专业Java相关毕业设计如何选题更容易通过...
  16. AWD比赛入门攻略总结
  17. 已知一个字符串,将字符串中的大写英文字母转变/转化成小写字母,小写字母转变为大写字母,并将转变后的字符串输出
  18. Bugku-CTF之细心 (想办法变成admin)
  19. 数据分析模型:OGSM模型
  20. 爆料:曹旭东创立自动驾驶公司Momenta 首次公开项目细节

热门文章

  1. c语言经典程序情书,计算机专业情书.doc
  2. 浏览器主页被篡改为2345
  3. 如何制作和发布你的第一款iPhone App!
  4. 【GPT4】GPT4 创作郭德纲姜昆相声作品的比较研究
  5. 注册app短信验证平台_APP短信对接选择怎样的平台
  6. Python数组中除以0但却不想报错处理方法
  7. 酷狗怎么转换音乐格式
  8. 7723java魔手机单机游戏下载_植物大战僵尸王(街机版)
  9. python操作Excel表格小妙招:只需十行代码,可以将多张Excel合并为一张
  10. FFMPEG基本操作命令指南(二)