Порядок разрушения статических объектов в C++

49
задан BartoszKP 17 July 2014 в 00:32
поделиться

7 ответов

Статические объекты разрушены в обратном порядке конструкции. И порядком конструкции очень трудно управлять. Единственная вещь, в которой можно быть уверены, состоит в том, что два объекта, определенные в той же единице компиляции, будут созданы в порядке определения. Что-либо еще более или менее случайно.

52
ответ дан 7 November 2019 в 11:33
поделиться

Другие ответы на это настаивают, что это не может быть сделано. И они правы, согласно спецификации - но там прием, который позволит Вам сделать это.

Создают только единственный статическая переменная, класса или структуры, которая содержит все другие вещи, как которые Вы обычно делали бы статические переменные, так:

class StaticVariables {
    public:
    StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { };
    ~StaticVariables();

    Var1Type *pvar1;
    Var2Type *pvar2;
};

static StaticVariables svars;

можно создать переменные в любом порядке, Вы должны, и что еще более важно, уничтожают их в любом порядке, Вы должны в конструкторе и деструкторе для StaticVariables. Для создания этого абсолютно прозрачным можно создать статические ссылки на переменные также, как так:

static Var1Type &var1(*svars.var1);

VoilГ - полный контроль.:-) Однако это - дополнительная работа, и вообще ненужный. Но когда это необходимо, очень полезно знать об этом.

25
ответ дан Head Geek 7 November 2019 в 11:33
поделиться

Короткий ответ: В целом, нет.

Немного более длинный ответ: Для глобальных статических объектов в единственной единице перевода порядок инициализации от начала до конца, порядок разрушения является точно обратным. Порядок между несколькими единицами перевода не определен.

при реальной необходимости в определенном порядке необходимо сделать это сами.

12
ответ дан gimpf 7 November 2019 в 11:33
поделиться

Статические объекты уничтожаются в реверсе порядка, в котором они создаются (например, сначала созданный объект уничтожается в последний раз), и можно управлять последовательностью, в которой статические объекты создаются, при помощи техники, описанной в Объекте 47, " Гарантируют, что глобальные объекты инициализируются, прежде чем они будут использоваться " в книге Meyers' Эффективный C++ .

, Например, чтобы определить в некотором роде, что я хотел бы, чтобы определенный объект был уничтожен в последний раз, или по крайней мере после другого статического onject?

Гарантируют, что это создается перед другим статическим объектом.

, Как я могу управлять порядком конструкции? не все помехи находятся в том же dll.

я проигнорирую (для простоты) то, что они не находятся в том же DLL.

Мой пересказ объекта Meyers' 47 (который 4 страницы длиной) следующие. Предположение, что Вы глобальный определяетесь в заголовочном файле как это...

//GlobalA.h
extern GlobalA globalA; //declare a global

... добавляют, что некоторый код к этому включает файл как это...

//GlobalA.h
extern GlobalA globalA; //declare a global
class InitA
{
  static int refCount;
public:
  InitA();
  ~InitA();
};
static InitA initA;

эффект этого будет состоять в том, что любой файл, который включает GlobalA.h (например, Ваш исходный файл GlobalB.cpp, который определяет Вашу вторую глобальную переменную) определит статический экземпляр класса InitA, который будет создан перед чем-либо еще в том исходном файле (например, перед Вашей второй глобальной переменной).

Этот класс InitA имеет статический ссылочный счетчик. Когда первый экземпляр InitA создается, который, как теперь гарантируют, будет, прежде чем Ваш экземпляр GlobalB будет создан, конструктор InitA может сделать то, что это должно сделать, чтобы гарантировать, что globalA экземпляр инициализируется.

12
ответ дан ChrisW 7 November 2019 в 11:33
поделиться

Нет, Вы не можете. Вы никогда не должны полагаться на другую конструкцию/разрушение статических объектов.

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

0
ответ дан Martin Cote 7 November 2019 в 11:33
поделиться

В стандартном C ++ это невозможно сделать, но, если у вас есть хорошее практическое знание внутреннего устройства вашего конкретного компилятора, этого, вероятно, можно достичь.

В Visual C ++ указатели на статические функции инициализации расположены в сегменте .CRT $ XI (для статической инициализации типа C) или сегменте .CRT $ XC (для C ++ type static init) Компоновщик собирает все объявления и объединяет их в алфавитном порядке.Вы можете управлять порядком, в котором происходит статическая инициализация, объявляя ваши объекты в соответствующем сегменте, используя, например,

#pragma init_seg

, если вы хотите, чтобы объекты файла A создавались до файлов B:

File A.cpp:

#pragma init_seg(".CRT$XCB")
class A{}A;

File B.cpp:

#pragma init_seg(".CRT$XCC")
class B{}B;

.CRT $ XCB объединяется до .CRT $ XCC . Когда CRT выполняет итерацию по указателям статических функций инициализации, она встречает файл A перед файлом B.

В Watcom сегмент XI, и варианты #pragma initialize могут управлять построением:

#pragma initialize before library
#pragma initialize after library
#pragma initialize before user

... подробнее см. В документации

]
4
ответ дан 7 November 2019 в 11:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: