Как сделать статическую депритилизацию, если деструктор имеет побочные эффекты, и объект доступа к деструктора другого статического объекта?

StackOverflow https://stackoverflow.com/questions/3143180

Вопрос

Существует простой и известной шаблон, чтобы избежать статической инициализации Fiasco, описанного в Раздел 10.13 FAQ C ++ Lite Lite.

В этом стандартном рисунке есть компромисс, сделанный в том, что либо построенный объект никогда не разрушается (что не является проблемой, если деструктор не имеет важных побочных эффектов), либо статический объект не может быть безопасно доступен из деструктора статического объекта (видеть Раздел 10.14 FAQ C ++ Lite Lite).

Итак, мой вопрос: как вы избегаете статической депринимализации Fiasco, если деструктор статического объекта имеет важные побочные эффекты, которые в конечном итоге должны произойти а также Статический объект должен быть доступен доход другого статического деструктора объекта?


(Примечание: FAQ-Lite упоминает, этот вопрос отвечает в FAQ 16.17 Часто задаваемые вопросы C ++: часто задаваемые вопросы М. Клина и и Г. Ломау. У меня нет доступа к этой книге, поэтому я задаю этот вопрос вместо этого.)

Это было полезно?

Решение

Функция статических объектов, таких как глобальные объекты, гарантированно уничтожаются (при условии, что они созданы).

Порядок разрушения - это обратное создание.
Таким образом, если объект зависит от другого объекта во время разрушения, вы должны гарантировать, что он все еще доступен. Это относительно просто, так как вы можете заставить порядок разрушения, убедившись, что порядок создания выполняется правильно.

Следующая ссылка о синдилонах, но описывает аналогичную ситуацию и ее решение:
Поиск проблем заказа статической инициализации C ++

Экстраполяция до общего случая ленивых инициализированных глобалей, как описано в FAQ Lite, мы можем решить эту проблему:

namespace B
{
    class B { ... };

    B& getInstance_Bglob;
    {
        static B instance_Bglob;
        return instance_Bglob;;
    }

    B::~B()
    {
         A::getInstance_abc().doSomthing();
         // The object abc is accessed from the destructor.
         // Potential problem.
         // You must guarantee that abc is destroyed after this object.
         // To gurantee this you must make sure it is constructed first.
         // To do this just access the object from the constructor.
    }

    B::B()
    {
        A::getInstance_abc();
        // abc is now fully constructed.
        // This means it was constructed before this object.
        // This means it will be destroyed after this object.
        // This means it is safe to use from the destructor.
    }
}
namespace A
{
    class A { ... };

    A& getInstance_abc()
    {
        static A instance_abc;
        return instance_abc;
    }
}

Другие советы

Пока статический деструктор другого объекта работает первым, вы в порядке. Вы можете заверить это, имея другой объект построен до «объекта A». Пока оба объекта объявлены в одном и том же блоке компиляции, они будут инициализированы в том порядке, в котором они появляются в источнике, и разрушаются в противоположном порядке.

Если вам нужно, чтобы это произошло через компиляционные единицы, вам удачи. Лучше - динамически создавать их во время выполнения и уничтожить их в конце основного, а не сделать их статическими.

Это немного взлома, но я бы добавил некоторые статические лолы, чтобы отслеживать порядок инициализации de, то объект, который заканчивается, последний, делает уборку, даже если это не является владельцем.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top