Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Область действия члена данных статического класса

Автор вопроса: CuriousGeorgeОтветов: 5

Если у меня есть класс:

Object.h

class Object
{
public:
    static int number;
};

Object.cpp

int Object::number = 5;

Гарантируется ли, что область действия Object::number переживет область действия любого созданного экземпляра Object? даже если он объявлен глобально в другом исходном файле?

  • Связь статики класса и нестатических экземпляров преднамеренна и различна. Object::number будет существовать даже тогда, когда никаких экземпляров Object не существует, не говоря уже о том, что они переживут любой конкретный экземпляр Object. Есть только один (если это не шаблон, но технически это не тот же класс, так как это будет сгенерированный вывод). WhozCraig 01.03.2013
  • Кстати, то, о чем вы спрашиваете, называется сроком службы, а не областью действия. Область видимости - это часть исходного файла, в которой видно имя. Время жизни - это период во время выполнения, когда объект существует. Steve Jessop 01.03.2013
  • @WhozCraig: С другой стороны, я считаю, что можно создать и использовать экземпляр Object до того, как Object::number будет инициализирован... Mooing Duck 01.03.2013
  • @MooingDuck - я думаю, это отвечает на точный вопрос ОП. Robᵩ 01.03.2013
  • @MooingDuck Мне пришлось бы серьезно погрузиться в время жизни объектов, глобальные инициализации и определения их формата в стандарте, прежде чем я смог бы подтвердить или опровергнуть, что это возможно, но меня ничуть не удивило бы, если бы это было так. Глобальная инициализация для меня всегда ненадежная вещь, поэтому я стараюсь ее избегать. WhozCraig 01.03.2013

c++classglobal-variablesstatic

Ответы

Ответ 1 · рейтинг 2 · Robᵩ

Рассмотрим эту программу g++:

#include <iostream>
#define X() (std::cout << __PRETTY_FUNCTION__ << "\n")

struct M {
 M() { X(); }
 ~M() { X(); }
};

struct C {
 C() { X(); }
 ~C() { X(); }
 static M m;
};
C c;
M C::m;
int main () { X(); }

В этой программе c должен быть инициализирован до C::m и должен быть удален после C::m. Если вы скомпилируете эту программу и рассмотрите ее вывод, вы увидите что-то вроде:

C::C()
M::M()
int main()
M::~M()
C::~C()

Итак, нет, в целом, "[срок жизни] [члена]" не "гарантированно превосходит [срок службы] любого созданного экземпляра объекта?"

Ответ 2 · рейтинг 5 · Mats Petersson

Да, он имеет "статическую продолжительность хранения", что означает, что он существует "все время" [если у него есть нестандартный конструктор, конструктор вызывается перед запуском "основного" - этого должно быть достаточно для большинства намерений и целей]

Ответ 3 · рейтинг 4 · Steve Jessop

Вроде того, но только потому, что int - особый случай. Например, предположим, что вы пишете в Object.cpp:

Object o = {};
int Object::number = 5;

Тогда объект o имеет статическую продолжительность хранения, как и Object::number. Номинально он создается до number и будет уничтожен позже, но, поскольку они оба являются POD, это уничтожение фактически не имеет никакого эффекта.

Однако если бы number и o имели нетривиальные деструкторы, то number был бы уничтожен до o. Тот факт, что number является статическим членом класса o, не дает ему особого отношения к порядку уничтожения.

Если o выключен в другом исходном файле, то порядок построения не указан, а порядок уничтожения является обратным порядком построения (опять же, это если у них были нетривиальные деструкторы - int является особым случаем, поскольку это не так).

Ответ 4 · рейтинг 3 · Mike Seymour

Да, по двум причинам:

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

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

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

Ответ 5 · рейтинг 1 · LihO

Стандарт гарантирует, что объекты с длительностью статического хранения существуют в течение всего времени работы программы.

C++03, 3.7.1 Длительность статического хранения §1:

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

и в вашем примере также актуален §4:

Ключевое слово static, примененное к члену данных класса в определении класса, дает срок статического хранения члена данных.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы