Я пытался получить необходимую информацию прямо из документа C ++ 03 Standard. Вот что я нашел:
Относительно деклараций const static
:
Согласно разделу 3.5.3 объекты, определенные на уровне пространства имен и объявленные const
, имеют по умолчанию внутреннюю связь . static
также объявляет объект уровня пространства имен для внутренней связи, поэтому нет необходимости объявлять объект static const
.
Также согласно Приложению D.2
Использование статического ключевого слова
не рекомендуется при объявлении объектов в
область имен (см. 3.3.5).
По поводу фиаско статической инициализации:
Поскольку переменные определены в заголовочном файле, они всегда определяются перед любыми другими статическими объектами, использующими их.
Из раздела 3.6.2.1:
Объекты со статической продолжительностью хранения
определяется в области имен пространства в том же
блок перевода и динамически
инициализируется должен быть инициализирован в
порядок, в котором их определение
появляется в блоке перевода.
Ответ 1: Это означает, что передача переменных в конструктор статического объекта должна быть в порядке.
Ответ 2: Однако проблема может возникнуть, если на переменные ссылаются из не встроенного конструктора статического объекта:
Ни в разделе 3.6.2.1, ни в 3.6.2.3 не указано, в каком порядке статические объекты в разных единицах компиляции инициализируются , если динамическая инициализация выполняется перед первым оператором main
.
Обратите внимание на следующее:
// consts.h
#include <string>
const std::string string1 = "ham";
const std::string string2 = "cheese";
// myclass.h
#include <string>
class MyClass
{
public:
MyClass();
MyClass(std::string str);
std::string Get() { return memberString; }
private:
std::string memberString;
}
// myclass.cpp
#include "consts.h"
#include "myclass.h"
MyClass::MyClass() : memberString(string1) {}
MyClass::MyClass(std::string str) : memberString(str) {}
// main.cpp
#include <iostream>
#include "consts.h"
#include "myclass.h"
MyClass myObject1;
MyClass myObject2(string2);
using namespace std;
int main()
{
cout << myObject1.Get(); // might not print "ham"
cout << myObject2.Get(); // will always print "cheese"
}
Поскольку myclass.cpp
имеет свою собственную копию переменных const
, они могут не инициализироваться при вызове MyClass::MyClass()
.
Так что да, переменные const
, определенные в заголовочных файлах, могут использоваться таким образом, который склонен к статической инициализации фиаско
Насколько я понимаю, это относится только к переменным, не требующим статической инициализации:
Из стандарта C ++ 03, раздел 3.6.2.1:
Объекты типов POD (3.9) со статическими
продолжительность хранения инициализируется с
константные выражения (5.19) должны быть
инициализируется перед любой динамикой
инициализация происходит.