Есть dll. В ней есть глобальные переменные, вот так:
dllbody.cpp
class Initalizer
{
public:
Initializer(std::string name)
{
names << name; // names не существует!
}
private:
static std::list<std::string> > names;
};
Initializer init1("hello");
Initializer init2("world");
Попался на том, что статический член класса еще не создан... Неужели статические члены класса находятся на одном уровне с глобальными переменными и тоже инициализируются в беспорядке?
Здравствуйте, leonty, Вы писали:
L>dllbody.cpp
L>L>class Initalizer
L>{
L>public:
L> Initializer(std::string name)
L> {
L> names << name; // names не существует!
L> }
L>private:
L> static std::list<std::string> > names;
L>};
L>Initializer init1("hello");
L>Initializer init2("world");
L>
А где у тебя names-то определяется?
Должно быть что-то типа такого:
std::list<std::string> > Initializer::names;
Initializer init1("hello");
Initializer init2("world");
Для одной единицы трансляции порядок инициализации глобальных переменных определён — это "сверху вниз", т.ч. должно работать.
Ну а если отвечать на твой вопрос по поводу порядка инициализации — то, да, статические переменные классов в этом плане ничем не отличаются от глобальных переменных. Их отличия от глобальных переменных скорее "косметические" — ограничение доступа (protected/private) и помещение имени в пространство имён (2 класса могут содержать статическое поле с одним именем). А в плане механики инициализации/разрушения они ничем не отличаются.
Если у тебя определения глобальных переменных всё же разнесены по разным единицам трансляции, то ты можешь применить следующий приём.
Вместо:
static std::list<std::string> > names;
Напиши:
static std::list<std::string> >& names()
{
static std::list<std::string> > inst;
return inst;
}
В таком случае переменная всегда будет инициализирована перед первым обращением (и как бонус переменную не надо дополнительно определять). Однако учти, что это будет работать только, если обращения к names() идёт из одного потока, ну или точнее так — первое обращение из одного потока, потому что инициализация статических переменных на уровне функции в общем случае не потокобезопасная.
Здравствуйте, remark, Вы писали:
R>А где у тебя names-то определяется?
R>Напиши:
R>R> static std::list<std::string> >& names()
R> {
R> static std::list<std::string> > inst;
R> return inst;
R> }
R>
R>В таком случае переменная всегда будет инициализирована перед первым обращением (и как бонус переменную не надо дополнительно определять). Однако учти, что это будет работать только, если обращения к names() идёт из одного потока, ну или точнее так — первое обращение из одного потока, потому что инициализация статических переменных на уровне функции в общем случае не потокобезопасная.
Да, names определяется в другом файле, просто забыл написать. Уже сделал этот вариант с функцией.
Поскольку работа с names идёт толко при загрузке dll, то проблем с потоками быть не должно.