A недавний вопрос привлек мое внимание к тому, как constexpr изменился на С++ 14. Новая функция заключается в том, что нестационарная переменная со статической продолжительностью хранения может быть инициализирована в статической фазе инициализации, если ее инициализатор состоит из конструктора constexpr, даже если тип переменной не является литеральным типом. Точнее, новая формулировка в [basic.start.init]:
Постоянный инициализатор для объекта
oявляется выражением, которое является константным выражением, за исключением того, что оно также может вызывать конструкторы constexpr дляoи его подобъектов, даже если эти объекты имеют нелиберальные типы классов [Примечание: такой класс может иметь нетривиальный деструктор; конец примечание]. Постоянная инициализация выполняется [...], если объект со статикой или длительностью хранения потока инициализируется вызовом конструктора, и если полное выражение инициализации является постоянным инициализатором для объекта [...]
Типичным примером является std::unique_ptr, который "никогда не должен быть хуже написанного вручную":
std::unique_ptr<int> p; // statically initialized by [unique.ptr.single.ctor],
// requires no code excution
int main()
{
p = std::make_unique<int>(100);
}
// p is destroyed eventually
До этого добавления статически инициализированные переменные были либо ссылочного типа, либо типа литерала, и поэтому имели тривиальные деструкторы. Но теперь статически инициализированная глобальная переменная может иметь нетривиальный деструктор.
Как устроен такой деструкторный вызов по отношению к деструкторам динамически инициализированных глобальных объектов по отношению к другим статически инициализированным и как упорядочиваются вызовы деструктора?