0

ご存知のように、関数の外で定義され、コンパイル単位が異なる変数の構築順序は固定されていません。この理解に基づいて、実行中にクラッシュする必要があると思われる単純なコードを考案しました。しかし、そうではありませんでした。ここにコードがあります。

/* table.h */
#include <iostream>
using namespace std;
class table {
public:
    int a;
    int b;
    table(table& t) {
        a = t.a;
        b = t.b;
    }
    void print(void) {
        cout << a << endl;
        cout << b << endl;
    }
};

/* f1.cpp */
#include "./table.h"
extern table t2;
table t1 = t2;

/* f2.cpp */
#include "./table.h"
extern table t1;
table t2 = t1;

/* core.cpp */
#include "./table.h"
extern table t1;
extern table t2;
int main(void) {
    t1.print();
    t2.print();
    return 0;
}

ご覧のとおり、t1 と t2 は相互に参照しています。どちらが最初に割り当てられるかはわかりませんが、一方が割り当てられていない他方にアクセスすることは明らかであり、これは完全な災害です。正常に動作するのはとても奇妙です。

4

3 に答える 3

1

グローバル オブジェクトの初期化は、翻訳単位間で順序付けされていません。

オブジェクトが使用前に確実に初期化されるようにする一般的な方法は、次のように関数にラップすることです。

myfoo.h:

#include "Foo.h"

Foo & myFoo();

myfoo.cc:

#include "myfoo.h"

Foo & myFoo()
{
    static Foo impl;
    return impl;
}

グローバル オブジェクトを必要とするすべての人は、グローバル オブジェクトを としてインクルードmyfoo.hし、参照しますmyFoo()

問題に対してこのアプローチを試してみると (初期化子を考慮して適切に変更されています)、同じ静的初期化を複数回入力するため、問題が不明確であることがわかります。

于 2013-09-17T15:32:45.943 に答える