Могу ли я получить статический сбой в порядке инициализации при доступе к статическим членам через статическую функцию? - PullRequest
2 голосов
/ 22 мая 2011

Этот конкретный код подвержен статическому порядку инициализации фиаско?Т.е. могу ли я предположить, что статическая инициализация в модуле компиляции "B" уже выполнена, когда я получаю доступ к статической функции-члену B?

// a.h
struct A {
    static int foo();
    static int var;
}

// a.cpp
#include <a.h>
int A::foo() {
    return var;
}
int A::var = 42;


// b.h
struct B {
    B::B();
    static int var;
}

// b.cpp
#include <b.h>
#include <a.h>
B::B() {
    var = A::foo();
}

// c.h
struct C {
    static B b;
}

// c.cpp
B C::b;

Или у меня есть такой код:

// a.h
static int &A::var();

// a.cpp
int &A::var() {
    static value = 42;
    return value;
}

int A::foo() {
    return var();
}

Ссылки на стандарт приветствуются.

1 Ответ

3 голосов
/ 22 мая 2011

Да, вы можете увидеть проблему при доступе через статическую функцию.
См. Пример ниже гарантированно не удастся.

Способ решить эту проблему - не получить доступ к «объектам длительности статического хранения» до запуска main.

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

// a.cpp
MyType&  A::getInstance()
{
    static MyType myInstance;
    return myInstance;
}

Пример гарантированного сбоя:

struct A
{
     static A  instanceA1;
     static A& getInstance() { return instanceA1;}
};

struct B
{
     static B instanceB1;
     static B& getInstance() { return instnaceB1;}
     A& member;

     B(): member(A::getInstance()) {}
}

B B::instanceB1;   // Constructure uses A::getInstance() which returns A::instance
                   // But A::instance has not been constructed yet.
                   // Order of instanciation in the same compilation unit is guranteed
                   // So we know this will not work.
A A::instanceA1;
...