ARM C++ABI:构造函数/析构函数返回值

ARM C++ ABI: Constructor/destructor return values

本文关键字:析构函数 返回值 构造函数 C++ABI ARM      更新时间:2023-10-16

我一直在阅读Clang源代码,发现了一些关于ARM C++ABI的有趣之处,但我似乎无法理解其理由。来自ARM ABI文档的在线版本:

此ABI要求C1和C2构造函数返回This(而不是void函数(,以便C3构造函数可以尾部调用C1构造函数,并且C1构造函数可以尾部调用C2。

(类似于非虚拟析构函数(

我不确定C1C2C3在这里引用了什么。。。本节是对通用(即安腾(ABI§3.1.5的修改,但该节(至少在本在线版本中(只是简单地说明:

构造函数返回void结果。

无论如何,我真的不明白这是什么目的:让构造函数返回this如何允许尾部调用优化,在什么情况下?

据我所知,构造函数唯一可以尾调用另一个具有相同this返回值的构造函数的情况是,派生类只有一个基类,一个平凡的构造函数体,没有具有非平凡构造函数的成员,也没有虚拟表指针。事实上,使用返回void的尾部调用进行优化似乎更容易,而不是更困难,因为这样就可以消除单个基类的限制(在多基类的情况下,从上次调用的构造函数返回的this指针将不是派生对象的this指针(。

我在这里错过了什么?ARM调用约定是否使this返回成为必要?

好的,来自@Michael的有用链接让这一切变得清晰。。。C1C2C3分别指安腾ABI:对"完整对象构造函数"、"基本对象构造函数"answers"完整对象分配构造函数"的名称篡改

  <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/"基对象构造函数"是派生类在构造基类子对象时调用的构造函数;CCD_ 21和CCD_。在virtual继承的情况下,C1构造函数可以通过对virtual基类构造函数的调用和对C2构造函数的尾调用来实现,因此如果前者返回this,则后者也应该返回CCD_ 28。

析构函数的情况略有不同,但有关联。根据ARM ABI:

类似地,我们要求D2和D1返回this,这样D0就不需要保存和恢复this,并且D1可以尾调用D2(如果没有虚拟基(。D0仍然是一个空函数。

D0/"删除析构函数"是在删除对象时使用的,它调用D1/"完整对象析构函数",然后用this指针调用operator delete以释放内存。使D1析构函数返回this允许D0析构函数使用其返回值来调用operator delete,而不必将其保存到另一个寄存器或溢出到内存;类似地,D2/"基本对象析构函数"也应该返回this

ARM ABI还增加了:

我们不需要到虚拟析构函数的thunk来返回this。这样的撞击必须调整析构函数结果,防止它尾部调用析构函数,并取消任何可能的保存。

因此,只有D1和D2析构函数的非虚拟调用才能返回this

如果我理解正确,这意味着只有当D0静态调用D1时(即在非virtual析构函数的情况下(,才能使用此保存-还原省略优化。