-
参考链接
-
简介
- 开发这个文档最开始由大几个公司起草。
- 也有一些独立开发者的加入,后来就开源了。
- 部分编译器的开发者按照了这个文档的规则进行实现
C++
编译器.
-
内容
-
关键字定义
-
alignment of a type T (or object X)
- 指的是类型
T
或者对象X
的字节对齐是多少. - 即
1,2,4,8
字节对齐. - 一般来说,一个结构体或类按照某字节对齐,那么这个对象所在地址,一般也是可以整除的.
- 比如类型
T
按照8
字节对齐,那么对于T X
,&X & 7 == 0
.
- 指的是类型
-
base class of a class T
- 类型
T
的所有父类. - 这里
base class
指的是T
以及其父类.
- 类型
-
proper base class of a class T
- 这里则是上面的特殊版本,不包含
T
本身. - 即指的是
T
的所有父类.
- 这里则是上面的特殊版本,不包含
-
virtual base class of a class T
- 即
T
通过virtual
继承的.struct T:virtual X
- 即
-
base object destructor of a class T
- 类
T
的基本析构函数. - 主要的功能: 为
T
声明的非static
成员变量执行析构的函数. 同时还包括其直接父类,直接父类不包括virtual
继承的.
struct A{ }; struct B{ }; struct C{ A a;}; struct T:public A,public B,virtual public C{ static A a; B b; };
- 在上面的案例中
base object destructor
的构建结果应该是: b
的析构函数,a
是静态不纳入其中.- 继承下来的
A,B
,调用其析构.C
是virtual
继承来的. - 最后: 析构里面只处理直接继承的父类,父类的父类则有父类来处理.递归式的.
- 说明: 现在的编译器把自定义和默认的都放在一起了.
- 类
-
basic ABI properties of a type T
- 类型
T
在ABI
中的基本信息. - 即一个类,在最终生成了之后,会为这个类添加对应的数据,已记录其数据的有效性和数据布局,数据对齐等信息.
- 这里是对类在
ABI
中的布局描述.
- 类型
-
complete object destructor of a class T
- 这里则是完整的析构函数,即自定义的析构函数.
- 即前面的
base object destructor of a class T
加上额外的. - 额外的就是用户自定义的,比如析构指针之类的.
- 所以用户自定义的在
base object destructor of a class T
的前面执行.
-
deleting destructor of a class T
- 则是
complete object destructor of a class T
加上额外的. - 这里的额外就是对
delete
进行了重载的函数. delete
在最前.没有的话就是默认的空.
- 则是
-
direct base class order
- 直接继承的顺序.
- 如前面的案例
struct T:public A,public B,virtual public C
. - 这里就是直接继承顺序就是:从左往右. 不同的实现可能不一样,可能是按照逆序.
-
diamond-shaped inheritance
- 菱形继承,百度一大堆.
- 简单说就是把继承关系图画出来,是一个菱形.
- 当然,这里说的菱形是特殊了,可能最终画出来也不是标准菱形.只是因为最简单的案例画出来确实就是菱形.
-
dynamic class
- 多态类.
- 即一个函数中有虚表.
- 虚表则说明这个类:
- 普通继承
public,protected,private
继承的父类里面有一个virtual
函数. - 也可能是
struct T:virtual A
,即virtual
的方式继承,也有. - 所以避免菱形继承的子类肯定有虚函数指针.是一个多肽类.
-
empty class
- 空的,假如
T
就是一个empty class
,那么sizeof(T) == 1
. - 为什么等于
1
,因为这是编译器这么做的,如此可以保证定义两个类,所在位置不一样,有一个唯一的地址. - 空类的特性就是: 可以有
static
成员,但是不能有普通成员. - 如果有普通成员,那么其必然是
type name:0;
这种,也可以是type :0;
,也可以是type s[];
,这几种没有不占空间的类型. - 可以有成员函数,但是不能有
virtual
类型的. - 可以继承,但是其继承的父类也必须是
empty
的. - 当然也不可以
virtual
继承. - **总之:**最终大小为
1
.
- 空的,假如
-
empty data member
data member
,即没有成员变量. 这里不要求sizeof(T) == 1
.- 要求当前类没有数据成员变量,可以有
virtual
函数,可以有static
,就是不能有成员变量.type name:0;
这类也不行.
-
inheritance graph
- 继承图,即将所有父类罗列出来,按照继承关系连接起来,形成的有向拓扑图.
- 就是最终的继承图.
- 菱形继承里面的案例图就是一个继承图.
-
inheritance graph order
- 继承顺序,遍历前面的
inheritance graph
,按照深度优先遍历.大多数都是这样.从子类到父类. - 所有的结点只遍历以此. 尽管
virtual
继承的可能出现多次,但是只遍历一次. 父类的顺序按照先后顺序从左往右遍历. - 比如
class A:public B,public C
就是A -> B -> C
. 这里的遍历是按照print,visit,visit
的方式遍历. - 这里的继承顺序和内存布局无半毛钱关系,但是可以在内存布局的时候参考.
- 继承顺序,遍历前面的
-
instantiation-dependent
TODO
-
morally virtual
X
是Y
的直接用virtual
继承的或着所示,X
是Y
的父类通过virtual X
继承的.- 那么
X
是Y
的morally virtual
. - 名义上的虚基类.
-
nearly empty class
sizeof(T) != 1
,且里面的数据都是指针. 即父类和自己都没有任何成员变量.全是虚函数和virtual
继承.- 如下描述:
- 没有成员变量,
static
的可以有. - 没有长度不为
0
的匿名字段,type name:0;
可以. 不匿名就是成员变量了. - 最多只有一个直接非
virtual
继承的父类,即class T:public X
.而且这个X
同样是nearly empty class
. - 所有的父类都不为空,所有父类都是
virtual
继承的, 且所有父类都公用一个虚表. - 这类最适合用来做
primary base classes
-
non-trivial for the purposes of calls
- 有意义的成员函数. 看成一个名词最好.参考https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-101/
- 有自定义的拷贝构造,移动构造,析构.
- 或者拷贝和移动构造是
delete
. - 满足上述条件一个即可.
- 目的:拥有上诉所设计的函数才能算是完整的定义。在进行临时变量的传递或者返回的时候,会执行对应的函数。如果没有,就是
trival
类型,那么就会根据ABI
的定义,在传递或返回的时候,直接memcpy复制即可. - 总结: 有自定义拷贝移动构造和析构或删除了拷贝移动构造则是non-trivial. 否则就是 trivial ,就直接拷贝内容即可.
- 主要还是和
C
区分,没有就用C
对待,有就用C++
对待.
-
POD
- 参考链接 https://stackoverflow.com/questions/146452/what-are-pod-types-in-c
- 简单来说就是没有构造析构和
virtual
函数.即在C++
中可以当成C
结构体的类型.
-
POD for the purpose of layout
- 类型如果是
POD
类型,即plain old data
,大多都满足. - 前面说了
POD
类型大多都满足,但是下面一个条件满足了,就不是POD for the purpose of layout
: pod
类型的union
或struct
,这两种类型中,如果存在一个成员变量的bit
比自身的bit
宽,那么就不是.int sss:33;
,int 32
位,而声明了33
位.- 或者是一个数组,元素类型不是
POD for the purpose of layout
. - 或者是
POD
类型中,有几个非静态成员变量的地址不唯一,存在交叉.比如struct{int a:1;int b:2;int c:5;};
,这里三个成员变量才占用一个字节.三个变量的地址公用.
- 类型如果是
-
potentially-overlapping subobject
- 父类或成员变量声明了
[[no_unique_address]]
属性.
- 父类或成员变量声明了
-
primary base class
- 当前类和某个父类共享了虚表.这个虚表的拥有者就是
primary base class
. - 共享虚表可以介于空间.
- 首先满足是多态类. 前面介绍的
nearly empty class
就适合用来选择primary base class
.
- 当前类和某个父类共享了虚表.这个虚表的拥有者就是
-
secondary virtual table
- 不是
primary
的虚表就是secondary
. - 一个多态类可能有多个
secondary virtual table
. 因为可能父类中有好几个virtual
继承,且没有选上primary base class
的.
- 不是
-
thunk
- 汇编代码,不是函数,和某个方法或者说操作绑定.
- 比如对于动态库中的符号,进行延迟绑定,就借助了一个
thunk
. - 这里一般用来修改
this
,进行偏移到正确的子类上操作. 或者说是将调用的函数修改为真正的函数,也可能在返回之后将值进行修改. thunk
应该尽量的短,太长了就建议作为函数创建,拥有自己的栈帧.
-
vague linkage
- 属于编译阶段,特别是处理内联函数和模板以及虚表. 在
obj
中编译一个有一个,那么就需要在链接阶段去重. - 在编译的时候可以当成只有一个,而不是多个重复的. 具体可以去看《程序员的自我修养》,此书中有关于编译去重的介绍.
- 属于编译阶段,特别是处理内联函数和模板以及虚表. 在
-
virtual table| vtable
- 多态类一般都有一个关联的表,对象共用.
- 这个表中存放了多态类的相关属性: 函数指针,virtual父类在内存中的偏移量等等.
-
virtual table group
- 类本身的虚表和其所有父类的虚表.
- 即
primary base class
的table
+secondary virtual table
.
-
01 常规概念
猜你喜欢
转载自blog.csdn.net/rubikchen/article/details/121407834
今日推荐
周排行