0

動的に割り当てられた静的グローバル オブジェクトについて非常に具体的な質問があります。私のプロジェクトでは、アプリケーションの存続期間中、スレッド全体のさまざまな場所からアクセスする必要があるオブジェクトはほとんどありません。アプリケーションの初期化時に を作成し、アプリケーションの終了時に破棄したいと考えています。だから私は次のようにしてみました、

ヘッダー ファイル: MyObjectFactory.h

class MyObjectFactory{
   public:
      static MyObject* GetMyObject();
};

ソース ファイル: MyObjectFactory.cpp

static MyObject* gMyObject = 0;

MyObject* MyObjectFactory::GetMyObject(){
    if(gMyObject == 0)
    {
        gMyObject = new MyObject();
    }
    return gMyObject;
}

このコードは機能しているように見えますが、いくつかクリアしたいことがあります。

  1. オブジェクトは一度だけ作成され、オブジェクトへの参照が返されます。( MyObject はテキストファイルのようなシステムリソースをほとんどカプセル化しないため、これが必要です)
  2. アプリケーションが終了すると、MyObject が破棄されます。
  3. オブジェクトによって作成されたヒープ ( new を使用しているため) またはグローバル メモリ ( static を使用しているため) はどこにありますか? または、OOP の原則に違反していますか?
  4. 複数のスレッドから MyObjectFactory::GetMyObject() を呼び出しても問題ありませんか?
  5. これは、Singleton に多少似たものを達成するための良い方法ですか?

あなたの入力を教えてください。

どうもありがとうございます!

4

3 に答える 3

2

オブジェクトは一度だけ作成され、オブジェクトへの参照が返されます。( MyObject はテキストファイルのようなシステムリソースをほとんどカプセル化しないため、これが必要です)

  • MyObject*参照型ではなくポインタ型です。gMyObjectへのポインタ型の変数ですMyObject

アプリケーションが終了すると、MyObject が破棄されます。

  • deleteそうではありません。誰もあなたのポインターを呼び出していないので、リークがあります。

オブジェクトによって作成されたヒープ ( new を使用しているため) またはグローバル メモリ ( static を使用しているため) はどこにありますか? または、OOP の原則に違反していますか?

  • を使用している場合new、オブジェクトは「ヒープ」に作成されます。staticオブジェクト自体ではなく、オブジェクトへのポインターにのみ適用されます。

複数のスレッドから MyObjectFactory::GetMyObject() を呼び出しても問題ありませんか?

  • そうではありません。同時スレッドがあり、オブジェクトがまだ構築されていない場合、複数の初期化が発生する可能性があります。

これは、Singleton に多少似たものを達成するための良い方法ですか?

  • そうではありません。または、そうかもしれませんが、シングルトンは通常、何かを達成するための悪い方法です (そして、通常はとだけ言いました)。
于 2012-05-29T15:46:24.340 に答える
2

頭痛を最小限に抑えて適切な破棄と適切な初期化の両方を実現する標準的な方法は、次のようにブロックローカルの静的を使用します。

foo.hpp:

struct Foo
{
    static Foo & get();
    // ...
};

foo.cpp:

#include "foo.hpp"

Foo & Foo::get()
{
    static Foo impl;
    return impl;
}

Foo::get()これで、コード内のどこでも言うことができます。ポインターも動的割り当てもありません。リークもありません。真に静的なシングルトン。

于 2012-05-29T15:46:47.700 に答える
0

オブジェクトは一度だけ作成され、オブジェクトへの参照が返されます。

プログラムがシングルスレッドの場合、はい (ただし、例では参照ではなくポインターを返します)。そうしないと、2 つのスレッドがオブジェクトの別々のコピーを作成する危険があります。その場合の動作は定義されていないため、実際には何か他のことが起こっています。

アプリケーションが終了すると、MyObject が破棄されます。

いいえ、 で作成されたオブジェクトはnewによってのみ破棄されdelete、自動的には破棄されないため、このオブジェクトはリークされます。それが問題になるかどうかは、使用するすべてのリソースがシステムによって自動的に再利用されるかどうかによって異なります。

オブジェクトによって作成されたヒープ ( new を使用しているため) またはグローバル メモリ ( static を使用しているため) はどこにありますか?

オブジェクトはフリー ストア (別名ヒープ) から割り当てられます。それへのポインタは静的です。

複数のスレッドから MyObjectFactory::GetMyObject() を呼び出しても問題ありませんか?

いずれかが呼び出す前に、オブジェクトが既に作成されていることを確認できる場合のみ。

これは、Singleton に多少似たものを達成するための良い方法ですか?

C++ でそれを実現する良い方法はありません。最善のアプローチは、グローバルにアクセス可能なオブジェクトを完全に避けることです。どこかに作成し、必要なものへの参照を渡します。

本当にグローバル オブジェクトが必要な場合は、いくつかのオプションがあり、それぞれに独自のデストラップがあります。

  • 単純なグローバル オブジェクト。これらが複数あり、それらの間に依存関係がある場合は、初期化注文の失敗に注意してください。
  • this への参照を返す、静的オブジェクトを含む関数。これは、使用時に初期化されることが保証されており、C++11 準拠の実装 (および以前の多くの実装でも) でスレッドセーフです。ただし、プログラムのシャットダウン中に、まだアクセスしようとしている他の静的オブジェクトの前に破棄される可能性があるという危険があります。アプローチのように、オブジェクトを動的に割り当ててリークすることで、おそらくそれを回避できます。スレッドセーフな構築を確保することで、実行時のオーバーヘッドが発生する場合もあります。
  • 複数のスレッドを起動する前に初期化されていることを確認するか、スレッドセーフを追加する限り、遅延割り当てされた動的オブジェクト(あなたが持っているような)。
于 2012-05-29T15:55:14.790 に答える