Ответ 1
Хорошо, полезная ссылка от @Michael сделала это понятным... C1
, C2
и C3
ссылаются на манипулирование именами "конструктора объектов", "конструктора базовых объектов" и "конструктор выделения объектов", соответственно, из Itanium 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
/ "complete" - это версия конструктора, которая вместо работы с уже распределенным хранилищем, переданным ему через параметр this
, выделяет внутреннюю память (через operator new
), а затем вызывает конструктор объектов C1
/ "complete", который является обычным конструктором, используемым для всего объекта объекта. Поскольку конструктор C3
должен возвращать указатель this
к вновь выделенному и сконструированному объекту, конструктор C1
должен также возвращать указатель this
для использования хвостового вызова.
Конструктор базового объекта C2
/"- это конструктор, вызываемый производными классами при построении подобъекта базового класса; семантика конструкторов C1
и C2
различается в случае наследования virtual
и может быть реализована по-разному для целей оптимизации. В случае наследования virtual
конструктор C1
может быть реализован с вызовами конструкторов базового класса virtual
, за которыми следует хвостовой вызов конструктора C2
, поэтому последний должен также возвращать this
, если прежний делает.
Случай деструктора немного отличается, но связан. Согласно ARM ABI:
Аналогично, мы требуем, чтобы D2 и D1 возвращали это так, чтобы D0 не нуждался в сохранении и восстановлении, а D1 может хвост D2 (если нет виртуальных оснований). D0 по-прежнему является функцией пустоты.
При удалении объекта используется D0
/ "удаление деструктора", он вызывает дескриптор объекта D1
/ "complete object" и вызывает operator delete
с указателем this
, чтобы освободить память. Наличие D1
деструктора return this
позволяет деструктору D0
использовать его возвращаемое значение для вызова operator delete
, вместо того, чтобы сохранять его в другом регистре или проливать его на память; аналогичным образом, деструктор базового объекта D2
/"должен также возвращать this
.
ARM ABI также добавляет:
Мы не нуждаемся в том, чтобы виртуальные деструкторы разворачивали это. Такой удар должен был бы отрегулировать деструкторы результат, предотвращая его от хвоста, вызывающего деструктор, и сводит на нет любую возможную экономию.
Следовательно, для возврата этого могут быть использованы только не виртуальные вызовы деструкторов D1 и D2.
Если я правильно понимаю это, это означает, что оптимизация save-restore-elision может использоваться только тогда, когда D0
вызывает D1
статически (т.е. в случае деструктора не virtual
).