c ++: инициализация статических строковых членов - PullRequest
1 голос
/ 21 сентября 2011

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

std::string A::id()
{
    std::stringstream sst; 
    sst << "id" << i;           
    i++;
    return sst.str();
}

  std::string B::str = A::id(); //prints "id0";
  std::string C::str = "str"; //prints str


  std::string D::str = B::str; //prints "" <-- what's wrong here?
  std::string D::str2 = C::str; //prints ""

Кажется, что переменные, на которые я ссылаюсь (B :: str и C :: str), еще не были инициализированы. Но я предполагаю, что при выполнении D :: str = B :: str C :: str инициализируется не позднее, и поэтому D :: str также должен содержать строку "id0".

Ответы [ 2 ]

10 голосов
/ 21 сентября 2011

Это Статическая инициализация Fiasco .

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

Следовательно, любой код, основанный на порядке инициализации таких объектов, неизбежно завершится сбоем, и эта проблема известна как Статическая инициализация Fiasco в C ++.

Ваш код основан на условии, что инициализация B::str и C::str происходит до D::str, что не гарантируется Стандартом.Поскольку эти 3 статических объекта продолжительности хранения находятся в разных единицах перевода, они могут быть инициализированы в любом порядке.

Как этого избежать?

решение состоит в том, чтобы использовать Построить при первом использовании идиому , короче говоря, это означает замену глобального объекта глобальной функцией, которая возвращает объект по ссылке.Объект, возвращаемый по ссылке, должен иметь вид local static . Поскольку статические локальные объекты создаются при первом прохождении контроля над их объявлением, объект будет создан только при первом вызове, и при каждом последующем вызове тот же объект будетбыть возвращен, таким образом имитируя поведение, которое вам нужно.


Это должно быть Интересное прочтение:

Как предотвратить «фиаско статического порядка инициализации»?


3 голосов
/ 21 сентября 2011

Не существует гарантированного порядка инициализации для статических переменных.Так что не надейся на это.Вместо этого начинайте их с реальных литералов, или, что еще лучше, инициируйте их во время выполнения, когда они действительно необходимы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...