2

この特定のコードは、静的初期化順序の大失敗を起こしやすいですか? つまり、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();
}

標準への参照を歓迎します。

4

1 に答える 1

3

はい、静的関数を介してアクセスすると問題が発生します。
失敗することが保証されている以下の例を参照してください。

これを解決する方法は、メインが開始される前に「静的ストレージ期間オブジェクト」にアクセスしないことです。

何らかの理由で「静的ストレージ期間オブジェクト」のコンストラクターからオブジェクトにアクセスする必要がある場合は、これらのオブジェクトをラップして、使用前に完全に構​​築されていることを保証する必要があります。これを行う最善の方法は、「静的関数オブジェクト」 (オンデマンドで構築される静的ストレージ期間オブジェクトの一種) を使用することです。

// 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;
于 2011-05-21T20:50:42.383 に答える