C1
好的,来自@Michael 的有用链接使这一切都变得清晰C2
...... C3
ABI:
<ctor-dtor-name> ::= C1 # complete object constructor
::= C2 # base object constructor
::= C3 # complete object allocating constructor
::= D0 # deleting destructor
::= D1 # complete object destructor
::= D2 # base object destructor
/ “C3
完整对象分配构造函数”是构造函数的一个版本,它不是对通过参数传递给它的已分配存储进行操作,而是在this
内部(通过operator new
)分配内存,然后调用C1
/“完整对象构造函数”,即用于完整对象情况的普通构造函数。由于C3
构造函数必须返回this
指向新分配和构造的对象C1
的指针,因此构造函数还必须返回this
指针才能使用尾调用。
/ “C2
基类构造函数”是派生类在构造基类子对象时调用的构造函数;C1
和C2
构造函数的语义在virtual
继承的情况下是不同的,并且为了优化目的也可以以不同的方式实现。在virtual
继承的情况下,C1
构造函数可以通过调用virtual
基类构造函数然后尾调用C2
构造函数来实现,因此如果前者调用,后者也应该返回this
。
析构函数的情况略有不同但相关。根据 ARM ABI:
类似地,我们要求 D2 和 D1 返回这个,这样 D0 就不需要保存和恢复这个,并且 D1 可以尾调用 D2(如果没有虚拟碱基)。D0 仍然是一个 void 函数。
/ “ D0
deleting destructor”在删除对象时使用,它调用D1
/“complete object destructor”,然后operator delete
用this
指针调用以释放内存。让D1
析构函数返回this
允许D0
析构函数使用其返回值来调用operator delete
,而不必将其保存到另一个寄存器或将其溢出到内存中;同样,D2
/"base object destructor" 也应该返回this
。
ARM ABI 还添加了:
我们不需要对虚拟析构函数的 thunk 来返回this。这样的重击必须调整析构函数的结果,防止它尾调用析构函数,并取消任何可能的保存。
因此,只能依靠 D1 和 D2 析构函数的非虚拟调用来返回this。
如果我理解正确,这意味着这种保存-恢复-省略优化只能在静态D0
调用时使用D1
(即在非virtual
析构函数的情况下)。