书名:C++对象模型详解
ISBN:978-7-115-65712-1
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 秦连松
责任编辑 龚昕岳
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
本书基于GCC/Clang编译器深入讲解C++对象模型的相关知识,涵盖C++对象的内部工作原理及底层的汇编实现机制。
本书先介绍对象模型的基本概念,并引入两个用于研究C++代码实现的开源工具——cppinsights和Compiler Explorer。接着,依次讲解C++数据语义学,即编译器如何布局C++对象模型中的数据成员;C++函数语义学,包括编译器如何实现C++中的多态、如何调用虚函数等;C++构造、析构语义学,涉及编译器对C++对象的构造和析构方式,包括全局对象和静态局部变量的构造等内容;C++异常处理,包括GCC中异常处理的实现方式及实践准则;C++运行时类型识别(RTTI)的实现原理,包括dynamic_cast算法的具体实现;C++ Name Mangling规则,包括GCC对C++代码中各个名称的编码方式。
本书适合有意深入理解C++对象模型、了解C++代码底层实现的读者阅读。阅读本书需要具备一定的C++基础知识。
对象模型是C++语言的精髓之一,学习对象模型是深入掌握C++语言内核的必经之路。本书从实践出发,层层递进,颇有庖丁解牛之功。
——李建忠
CSDN高级副总裁,Boolan首席技术专家,C++标准委员会委员
C++对象模型是介于宏观的C++语言和底层的汇编语言之间的抽象层,它是C++区别于其他主流高级编程语言的一大特色,也符合Bjarne Stroustrup从C++极早期版本就设定的语言文化——C++本身就使用C++来编译,新版语义在旧版语义的基础上构建。很高兴看到C++对象模型领域再添一本由国人执笔、基于Modern C++全面重构的力作。所有有志于深度理解C++语言并紧跟其最新进展的开发者,都应该仔细阅读本书并掌握其中讲解的思维和工具。
——高博
卷积传媒CEO,《C++覆辙录》《Effective Modern C++(中文版)》译者
C++对象模型久负盛名,本书系统讲解C++对象的内存布局、虚函数表、多继承、构造和析构流程、异常处理和运行时类型识别(RTTI)等内容,并结合cppinsights与Compiler Explorer两个工具所提供的直观的代码实例和汇编分析,深入剖析C++对象模型的内部工作原理,特别是在GCC和Clang编译器中的实现细节,实用性很强。
相比《深度探索C++对象模型》等经典图书,本书更贴近现代编译器的实现,聚焦GCC的Itanium C++ ABI规范,适合Linux平台开发者解决C++工程问题。此外,本书作者针对常见的编译器差异和性能调优进行了补充,使得本书内容更适合当前主流的C++开发需求。
对于想要提高个人C++开发修养、修炼C++编程内功的读者而言,本书无疑是一本兼具实用性与理论深度的参考书。
——何荣华(墨梵)
宝马自动驾驶软件专家,《C++20高级编程(第5版)》
《C++ Templates(第2版)中文版》《C++ Core Guidelines解析》译者
如果你习惯通过实践习得知识,C++对象模型是学习面向对象编程的理想切入点。C++对象模型领域的经典图书《深度探索C++对象模型》已经出版了近30年,其中所依赖的CFront编译器早已退出历史舞台。本书基于当下流行的GCC/Clang编译器对C++对象模型进行诠释,是新一代开发者不可错过的实战指南。
——凌杰
独立开发者,《C++程序设计(第3版)》译者
我在即将硕士毕业并面临找工作时非常纠结:选择硬件方向还是软件方向?如果选择软件方向,选择哪种编程语言?由于我在本科和研究生阶段做过信号处理与图像处理等相关工作,加之我个人也喜欢挑战和研究,因此在综合考量后我决定从事与C++相关的软件工作。毕业后,我先在百度从事C++相关工作,随后在字节跳动负责基础架构相关的工作,目前在小米从事虚拟机相关的工作。我一直在C++的学习与实践中持续精进。
C++是一门多范式编程语言。结合个人学习与实践经验,我将C++技术体系划分为以下部分。
● C++基础知识。该部分我推荐的学习材料为《C++ Primer Plus(第6版)中文版》和《C++ Primer 中文版(第 5 版)》,前者适合零基础入门,后者讲解得更深入一些。
● C++模板编程。该部分主要包括标准模板库(Standard Template Library,STL)和模板元编程的相关概念,主要的学习材料为C++ Templates: The Complete Guide, 2nd Edition(中文版为《C++ Templates(第2版)中文版》)。
● C++并发编程。该部分主要包括使用现代C++进行多线程编程的相关概念,主要的学习材料为C++ Concurrency in Action, 2nd Edition(中文版为《C++并发编程实战(第2版)》)。
● C++对象模型。该部分主要包括C++中多态的实现原理、对象的内存布局等相关概念,主要的学习材料为Inside the C++ Object Model(中文版为《深度探索C++对象模型》)。
● C++最佳实践。该部分主要包括如何写出可读性强、安全性高、性能好的C++代码,主要的学习材料为Effective Modern C++(中文版为《Effective Modern C++(中文版)》)、Effective C++: 55 Specific Ways to Improve Your Programs and Designs, 3rd Edition(中文版为《Effective C++:改善程序与设计的 55 个具体做法 中文版(第三版))和C++ Core Guidelines Explained(中文版为《C++ Core Guidelines解析》)。
本书主要讲解C++对象模型。写作本书的契机源自一次项目故障。当时我们在一个库的接口类中增加了一个虚函数接口,并通过静态库的方式将其提供给业务方使用,这导致业务方的程序崩溃,发生了大面积的coredump(在程序发生异常且该异常在进程内部没有被捕获的情况下,操作系统把进程此刻的内存、寄存器状态、运行堆栈等信息转储保存在一个core文件里)。为此,我复习了《深度探索C++对象模型》一书。同时,我还用GDB深入研究了GCC是如何实现C++对象模型的。在实验过程中,我发现GCC所模拟的C++对象模型并不符合《深度探索C++对象模型》中所描述的对象模型。例如,GCC的虚表布局和《深度探索C++对象模型》中所描述的不一致,并且GCC还会生成VTT(Virtual Table Table,虚表列表)。因为我的工作是基于Linux平台进行C++开发,并且日常用到的编译器为GCC和Clang,所以我决定彻底搞清楚运用GCC/Clang实现C++对象模型的原理,这本书便是我的研究成果。
本书分为8章,主要内容如下。
第1章“概述”介绍对象模型的基本概念,如果你有一定的C++基础,可以跳过本章。
第2章“工具”介绍cppinsights和Compiler Explorer这两个用于研究C++代码实现的开源工具,并利用这两个开源工具研究lambda表达式的相关概念。
第3章“数据语义学”主要讲解GCC如何实现C++对象模型中数据成员的布局。
第4章“函数语义学”主要讲解GCC如何实现C++中的多态、如何调用虚函数等。
第5章“构造、析构语义学”主要讲解GCC如何构造和析构C++对象,包括全局对象和静态局部变量的构造等内容。
第6章“异常处理”主要讲解GCC中异常处理的实现,以及进行异常处理的实践准则。
第7章“运行时类型识别”主要讲解运行时类型识别的实现原理,包括dynamic_cast算法的实现。
第8章“Name Mangling规则”主要讲解GCC如何对C++代码中的各个名称进行编码。
本书从实际代码出发,研究GCC是如何实现C++对象模型的,并从汇编层面进行深入探究。在GCC和Clang编译器中,C++对象模型均是基于Itanium C++ ABI实现的,因此GCC中的C++对象模型的实现均可应用于Clang编译器。
本书适合有一定C++基础、有意深入研究C++的工程师学习。我希望本书能真正帮助到你,带你体会C++的乐趣和魅力。由于目前互联网企业中与Linux相关的岗位使用的编译器大多为GCC/Clang,本书有助于相关岗位的读者更好地学习和工作。
本人并非GCC的专业研究者,书中难免存在疏漏,欢迎读者批评指正,我的邮箱是qls315hfut@126.com。
最后,感谢前辈们提供的开源工具cppinsights和Compiler Explorer。这两个工具使我在本书的写作中事半功倍。感谢我的家人对我的理解,尤其是我的爱人钟元杰,正是有了你们的支持,我才能够全身心地投入本书的写作。感谢人民邮电出版社的龚昕岳编辑和武晓燕编辑指导并帮助我完善了这本书。感谢我的好友高栋在百忙之中对本书进行了审阅并提出了很多宝贵的修改意见,促使本书能早日同读者见面。
秦连松
本书提供如下资源:
● 本书配套源代码;
● 本书思维导图;
● 程序员面试手册电子书;
● 异步社区7天VIP会员。
要获得以上资源,您可以扫描右侧二维码,根据指引领取。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区(https://www.epubit.com),按书名搜索,进入本书页面,单击“发表勘误”按钮,输入您发现的错误信息,然后单击“提交勘误”按钮即可(见下图)。本书的作者和编辑会对您提交的错误信息进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们。
如果您所在的学校、培训机构或企业想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发送给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作者与读者的在线交流互动,以及传统出版与数字出版的融合发展。
“异步图书”是异步社区策划出版的精品IT图书的品牌,依托于人民邮电出版社在计算机图书领域30余年的发展与积淀。异步图书面向IT行业及各行业的IT用户。
C++是一种多范式编程语言,该语言的核心之一是对象。在C++中,对象具有如下属性。
● 大小(由sizeof获得该属性)。
● 对齐限制(由alignof获得该属性)。
● 存储期(分为automatic、static、dynamic、thread-local)。
● 生命周期。
● 类型。
● 值。
● 名称(可选)。
“C++对象模型”是C++语言中一个非常重要的概念,它定义了内存中对象的布局和访问方式,包括虚函数、多继承、模板等特性的实现方式,对于理解C++程序的底层实现和进行高效的C++编程有着非常重要的意义。因此,每一个C++程序员都有必要了解C++对象模型的相关知识。
C++对象模型的一个关键特征是虚函数。一个类的虚函数成员是指以virtual开头声明的函数,例如在类Q中声明一个print虚函数:
class Q { public: virtual ~Q() = default; virtual void print(); };
C++中多态的实现需要保证一个类继承了另一个声明有虚函数的类,并且继承类型为public,例如类Z继承自类Q:
class Z : public Q { public: void print() override; };
对于拥有虚函数的类而言,对象模型需要考虑的问题包括虚函数存放的位置、以何种方式存放、如何调用相应的虚函数等。同时,C++对象模型还需要考虑虚函数在多态场景下的实现。
根据“C++之父”本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)的《C++语言的设计和演化》一书,在实现C++多态时,编译器会将对象中的虚函数的地址搜集起来并放到一个表格中,然后在对象中增加一个成员vptr来指向这个拥有虚函数地址的表格;对于类的其他成员函数(包括静态成员函数和非静态成员函数),编译器将其放置在对象内存(即栈或堆中为了存放该对象而分配的内存)之外的某处,一般为进程的代码区;对于定义在类中的非静态数据成员,编译器将其放置在对象内存之中;对于静态数据成员,编译器将其放置在对象内存之外的某处,一般为进程的数据区。例如,更改类Q的定义如下:
class Q { public: virtual ~Q() = default; virtual void print(); void print(int); static void need(int); private: static int a_; int b_; };
按照本贾尼所设想的内存模型规则,类Q的对象的内存布局如图1-1所示。
图1-1
为了实现多态,C++又引进了运行时类型识别(Run Time Type Identification,RTTI),此时若类Z公共继承自类Q,则类Z的对象的内存布局如图1-2所示。
图1-2
随着不同编译器的出现,相应的C++对象模型的实现也有所变化,但总体上均是基于本贾尼设计的方案进行变动。
本书主要研究的是GCC/Clang编译器针对C++对象模型的实现。在GCC和Clang编译器中,C++对象模型均是基于Itanium C++ ABI实现的,因此GCC中的C++对象模型的实现均可应用于Clang编译器。本书将围绕GCC展开,讲解其C++对象模型的实现。