c++在对象的构造时做了什么手脚?——《深度探索c++对象模型》阅读笔记之一
2021/6/21 20:30:25
本文主要是介绍c++在对象的构造时做了什么手脚?——《深度探索c++对象模型》阅读笔记之一,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
《深度探索c++对象模型》是《c++ primer》的作者Lippman所写的一本书,Lippman从自己参与开发cfront的经历出发,深度剖析了c++中对象的相关特性是如何被实现的。
这本书相对其他的各种c++特性解读,用法,最佳实践的书来说,相对艰深晦涩,其面对的也不是刚入门的C++ 学习者,而是想要了解C++在幕后做了什么的人。
这本书的作用应当是消除程序员脑海中的不确定性,揭开C++对象表面的魔法。一个对象,其定义, 创建,调用方法,析构等等,编译器有为你做了什么,又没做什么,如果想要真正的了解C++对象的工作机理,阅读这本书是大有裨益的。
本笔记是为了记录一些阅读中的知识点而设立,同时也是消化知识的一个过程。
以下内容是对书中第二章《The semantics of constructors》的消化梳理
1. 默认构造函数
对于简单的class中,我们经常略过对默认构造函数的声明和定义,编译器会照顾好一切,我们只要调用就行。
但是如果说究其根本,我们必须问,编译器真的为每个Class创建了默认构造函数吗?
为何这么问,因为抛去所有的对象特性的外衣,它仍然是一个函数,真的需要对每一个实例都调用一次这个函数吗?
假如说我依照c语言中的习惯定义了以下这个sturct:
1 struct point{ 2 int x; 3 int y; 4 };
我只想像在c语言一样,将这个只看做是几个基本类型变量的组合来使用,那么每次创建一个point实例,都要调用一次构造函数,这也太疯狂了!
c++的设计者们也是这样想的,有些时候,默认构造函数是完全不需要的,只需要分配好内存即可,这时我们说这是一个trivial的默认构造函数,只是观念上存在,但是编译器并不会生成相关代码。
编译器只在以下特定的几种情况下会合成一个默认构造函数
1.1 成员中有拥有默认构造函数的对象
1 class bar{ 2 //有默认构造函数 3 }; 4 5 class foo { 6 bar member; 7 };
当一个类中的成员是一个拥有默认构造函数的类时,编译器就无法袖手旁观了,它必须给这个类加上一个合成的默认构造函数,以调用其成员的默认构造函数。
当有多个这样的成员类时,合成的默认构造函数会按照声明顺序进行调用成员的默认构造函数。
如果说我们已经自己定义了默认构造函数呢? 那么编译器会向我们定义的函数前插入代码来初始化成员对象
1.2 继承自有默认构造函数的基类
1 class base{// 有构造函数}; 2 class derived :public base{};
这种情况是下,因为继承的性质使然,派生类必然需要调用父类的默认构造函数,所以编译器一定要合成一个默认构造函数
1.3 带虚函数的类
c++中动态多态的展现,需要通过虚函数,其实现是通过虚函数表来做到的。存在虚函数的类中,在实例化时加入一个指向虚函数表的指针,做这件事必须通过构造函数来实现。
1.4 继承自虚基类的类
虚基类也是动态的,在编译期无法确定其内存位置,所以必然也需要有指针指向,在对象创建时,对这个指针进行操作来确定虚基类的内存位置。 那么为了实现这个功能,必然需要合成默认构造函数
2. 拷贝构造函数
对于拷贝构造函数,不少人会有迷糊的感觉,觉得编译器会给每一个类合成一个,但是实际远不是这样的,
因为对于部分情况,拷贝构造函数是没有任何必要的,只需要进行所谓的 bitwise copy就行,即把对象对应的二进制内容原封不动的复制一份就行
但在一些情况下,编译器会压抑bitwise copy, 为类合成一份拷贝构造函数
2.1 当成员有拥有一个拷贝构造函数时
同默认构造函数类似,一个成员拥有拷贝构造函数(无论时被编译器合成的,还是自己显式定义的)时,该类就不能进行bitwise copy了,需要合成拷贝构造函数。
否则就无法调用成员的拷贝构造函数
2.2 继承自拥有拷贝构造函数的基类
和默认构造函数类似,拷贝时必须调用基类的拷贝构造函数,所以必然需要合成
2.3 类拥有虚函数时
在这种情况,拷贝构造函数需要设置虚函数表,不能理解的话考虑用一个派生类对象初始化基类对象,这时必然需要设置成员中的虚函数表指针重新指向基类的虚函数表。
2.4 类派生自虚基类时
和默认构造函数类似,需要保证其虚基类指针的正确设定,必然需要合成拷贝构造函数
本章中还谈论了 NRV优化其利弊和形式,以及面试官很喜欢的初始化列表的问题。这些暂时就不写了。
这篇关于c++在对象的构造时做了什么手脚?——《深度探索c++对象模型》阅读笔记之一的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享