Опять инициализация статичских переменных
От: leonty  
Дата: 10.04.10 13:57
Оценка:
Есть 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");


Попался на том, что статический член класса еще не создан... Неужели статические члены класса находятся на одном уровне с глобальными переменными и тоже инициализируются в беспорядке?
Re: Опять инициализация статичских переменных
От: remark Россия http://www.1024cores.net/
Дата: 10.04.10 14:38
Оценка: 2 (1) +1
Здравствуйте, 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() идёт из одного потока, ну или точнее так — первое обращение из одного потока, потому что инициализация статических переменных на уровне функции в общем случае не потокобезопасная.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Опять инициализация статичских переменных
От: leonty  
Дата: 10.04.10 14:43
Оценка:
Здравствуйте, 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, то проблем с потоками быть не должно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.