Подтвердить что ты не робот

Когда инициализируются статические члены класса С++?

Кажется, нет легкого ответа на это, но есть ли какие-либо предположения, которые можно безопасно сделать, когда можно получить доступ к полю статического класса?

EDIT: Единственное безопасное предположение состоит в том, что вся статика инициализируется до начала программы (вызов main). Итак, до тех пор, пока я не ссылаюсь на статику из другого статического кода инициализации, мне не о чем беспокоиться?

4b9b3361

Ответ 1

Стандарт гарантирует две вещи: объекты, определенные в одной и той же единице перевода (обычно это означает .cpp файл), инициализируются в порядке их определений (не декларации):

3.6.2

Хранилище для объектов со статической продолжительностью хранения (basic.stc.static) должно быть инициализировано нулем (dcl.init) перед любой другой инициализацией. Нулевая инициализация и инициализация с постоянным выражением коллективно называются статической инициализацией; вся другая инициализация - это динамическая инициализация. Объекты типов POD (basic.types) со статической продолжительностью хранения, инициализированные константными выражениями (expr.const), должны быть инициализированы до начала любой динамической инициализации. Объекты со статической продолжительностью хранения, определенные в области пространства имен в одной и той же системе перевода и динамически инициализированной, должны быть инициализированы в том порядке, в котором их определение появляется в блоке перевода.

Другая гарантированная вещь заключается в том, что инициализация статических объектов из единицы перевода будет выполняться до использования любого объекта или функции из этой единицы перевода:

Определяется реализацией независимо от того, выполняется ли динамическая инициализация (dcl.init, class.static, class.ctor, class.expl.init) объекта пространства имён перед первым утверждением main. Если инициализация отложена до некоторого момента времени после первого утверждения main, она должна произойти до первого использования какой-либо функции или объекта, определенного в той же самой единицы перевода, что и объект, который будет инициализирован.

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

<ы > РЕДАКТИРОВАТЬ Как указано в комментарии Suma, также гарантируется, что они инициализируются до ввода main.

Ответ 2

Они инициализируются до запуска программы (т.е. до ввода main).

Если в одном файле CPP есть два или более определений (статических данных), они инициализируются в последовательности, в которой они определены в файле (тот, который был определен ранее/выше в файле, был инициализирован до следующего).

Если в более чем одном CPP файле есть два или более определений (статических данных), последовательность, в которой обрабатываются файлы CPP, undefined/specific-specific. Это проблема, если конструктор глобальной переменной (вызываемый до запуска программы) ссылается на другую глобальную переменную, определенную в другом файле CPP, который, возможно, еще не был создан. Тем не менее, пункт 47 "Эффективного С++" Meyers (который называется "Убедитесь, что глобальные объекты инициализированы до их использования" ) описывает описание рабочего процесса...

  • Определите статическую переменную в файле заголовка (она статическая, поэтому вы можете иметь несколько экземпляров ее без жалобщика)

  • Попросите конструктор этой переменной вызывать все, что вам нужно (в частности, построить глобальные синглтоны, объявленные в заголовках)

..., который, по его словам, является техникой, которая может использоваться в некоторых файлах заголовков системы, например. чтобы глобальная переменная cin была инициализирована до того, как ее используют конструкторы статических переменных.

Ответ 3

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

TypeX* Class2::getClass1Instance()
{
    static TypeX obj1;
    return &obj1;
}

код > Примечание. В более раннем ответе говорится:

Другая гарантированная вещь заключается в том, что инициализация статических объектов из единицы перевода будет выполняться до использования любого объекта или функция из этой единицы перевода

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

Ответ 4

Они могут быть инициализированы в файлах файла реализации (.c/cpp/cc). Не инициализируйте их в .h, поскольку компилятор будет жаловаться на несколько определений.

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

Ответ 5

Я считаю, что его можно получить в любое время во время выполнения. Остается undefined порядок инициализации статических переменных.

Ответ 6

На этот вопрос нет абсолютно тривиального ответа, но в основном они инициализируются непосредственно перед тем, как управление передается в точку входа (основную) вашей программы. Порядок, в котором они инициализированы, (насколько мне известно) undefined и может быть специфичным для компилятора.

EDIT: Чтобы уточнить, ваше добавленное предположение верно. Пока вы только обращаетесь к нему после основного входа, вам не нужно беспокоиться о том, когда/как его инициализировать. К этому времени он будет инициализирован.

Ответ 7

Я думаю, что основной поток процесса выполнит следующие пять шагов в порядке

  • инициализация библиотеки CRT

  • статическая инициализация

  • выполнение функции main()

  • статическая унификация

  • унификация библиотеки CRT

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

class A;
static auto_ptr<A> a(auto_ptr<A>(&GetStaticA()));
A &GetStaticA(void)
{
    static A *a = NULL; //the static basic type variables initialized with constant experession will be initialized earlier than the other static ones
    if (a == NULL)
    {
         a = new A();
         return *a;
    }
}