12

かなりのコードでグローバル リソースを設定する必要があるコードがあります。

globalClass foo;  // global variable / object; give it a memory space to live

void doSomething( void )
{
  foo.bar();      // use the global foo object
}

int main( int argc, const char *argv[] )
{
  foo( argc );   // foo can only be instantiated in main as it's using
                 // information that's only available here

  doSomething(); // use the global foo object

  return 0;
}

ご覧のとおり、fooはグローバル スコープですが、そのコンストラクタを呼び出すには、 内でのみ利用可能な情報が必要ですmain

どうすればそれを達成できますか?

私が理解できる唯一の解決策は、へfooのポインターを作成するglobalClassことですが、それでは、を使用するたびにポインターが参照解除されますfoo。これは、タイトなループで使用するとパフォーマンスの問題を引き起こす可能性があります...

PS: 実際のプログラムmaindoSomethingは、別のファイルに存在します。fooもちろん、インスタンス化される前にアクセスされないことが保証されています。

4

3 に答える 3

6

関数内に変数fooとして持つのはどうですか?staticそうすれば、関数が呼び出されたときにのみインスタンス化されます。

globalClass& getThing()
{
  static globalClass thing;
  return thing;
}

void doSomething(const globalClass& thing);

int main()
{
  const globalClass& x = getThing();
  doSomething(x);  
}
于 2012-12-01T23:49:25.810 に答える
5

あなたが言ったようにポインタを使うことは最も簡単でクリーンなことです。ポインターの逆参照のオーバーヘッドは、実際にはそれほど多くありません。オーバーヘッドが目立つことを実際に示していない限り、これを使用することをお勧めします。

2番目のオプションは、の構築と初期化globalClassを2つの別々のメソッドに分離することです。コンストラクターは、外部情報を必要としない最も単純なことだけを実行し、外部情報を組み込むために、init(argc)または内部のあらゆるものを呼び出します。main

次のように、割り当てを使用してfooを初期化することもできます。

globalClass foo;

int main(int argc, const char *argv[]) {
    globalClass bar(argc);
    foo = bar;
}

これは基本的に一時変数を使用して初期化を行い、結果をコピーします。

于 2012-12-01T23:53:05.907 に答える
1

間接化が必要なく、クリーンアップを自分で行うことを気にしない場合は、次のような本当にひどいハックがあります。

union ClassHolder
{
    globalClass x;
    char buf[sizeof globalClass];

    constexpr ClassHolder() noexcept : buf() { }
};

ClassHolder h;
globalClass & foo = h.x;

int main()
{
    new (static_cast<void *>(&h.x)) globalClass(arg1, arg2, arg3);

    // main program

    h.x.~globalClass();
}
于 2012-12-02T00:15:05.320 に答える