0

作成されたオブジェクトへのポインターを返す静的ファクトリコンストラクターを持つクラスがあります。

オブジェクトを名前空間内の静的オブジェクトとして宣言する必要がありますが、正しく削除する方法がわかりません

class Foo
{
   public:
   Foo(int, int* );
   virtual ~Foo();
   static Foo* MyFooInitializer(int n )
   {
      int *p = new int[n];
      for (int i=0; i<n; i++)
         p[i]=i;

      Foo *ret = new Foo(n,p);
      delete p;
      return ret;
   }
   int someFooFunction(int a);
}

次に、私の名前空間にstatic inline関数があります

namespace MyNamespace
{

    static inline void  myfunction()
    {
        static Foo  *foo1 = Foo::MyFooInitializer(10); 
        int y = somevalue();
        int x = foo1->someFooFunction(int y);
    } 
}

オブジェクトが削除されることはないので、明らかにここでメモリリークが発生します。

重要な事実は、foo1が静的として宣言される必要があるということです。これは、一度作成されると、すべてのプログラムで同じオブジェクトであり、一意である必要があるためです(いくつかの変数を追跡します)。

おそらくこれは設計上の問題ですが、プログラムが終了したとき、またはプログラムを明示的に削除して再初期化するときに削除する方法がわかりません。

解決:

私はこのように本体を変更しましたMyFooInitializer

   static Foo* MyFooInitializer(int n )
   {
      int *p = new int[n];
      for (int i=0; i<n; i++)
         p[i]=i;

      static Foo ret = Foo(n,p);
      delete[] p;
      return &ret;
   }

これにより、プログラムの終了時にすべてのメモリを正しく解放できます。Valgrindは、すべてのヒープメモリが解放されたと言います。

4

3 に答える 3

4

ここでそのFooをヒープに割り当てる必要はありません。

static Foo* MyFooInitializer(int x) {
    static Foo some_foo(x);
    return &some_foo;
}

そのコードにはリークはなく、プログラムが終了するとFooは破棄されます。

によって返されるポインタがMyFooInitializer実際にから継承するクラスを指しているFoo場合は、静的変数の派生型を使用する必要があることに注意してください。

static Foo* MyFooInitializer(int x) {
    static SomeFooDerived some_foo(x);
    return &some_foo;
}

編集:あなたは実際の関数本体を提供したので、私の答えは有効です。あなたはこのようにします:

static Foo* MyFooInitializer(int n ) {
   // Don't know what this p is, anyway...
   int *p = new int[n];
   for (int i=0; i<n; i++)
      p[i]=i;

   static Foo ret(n,g); // what is g?
   delete[] p; // smart pointer plx
   return &ret;
}
于 2012-06-21T12:15:36.743 に答える
0

どうですか

static inline void  myfunction()
{
    static std::unique_ptr<Foo> foo1(Foo::MyFooInitializer(10));
    int y = somevalue();
    int x = foo1->someFooFunction(int y);
} 
于 2012-06-21T12:16:25.893 に答える
0

どうしてもfoo1を動的に作成する必要がある場合は、追加のクラスを作成し、値によって静的/グローバルにします。次に、そのデストラクタを使用してオブジェクトを削除します。

class MasterControlClass
{
    public:
    Foo* foo1;
    MasterControl(){foo1 = NULL;}
    ~MasterControl(){delete(foo1), foo1 = NULL;}
};



static inline void myfunction()
{
     static MasterControlClass mcp;
     mcp.foo1 = Foo::MyFooInitializer(10); 
}

このようにして、プログラムが終了すると、mcp desctructorが呼び出され、クリーンアップが実行されます。再初期化する場合は、割り当てごとにfoo1を削除する必要があります。追加するだけです。

if(mcp.foo1)
{
    delete mcp.foo1;
    mcp.foo1= NULL;
}

またはさらに良いことに、それをmcpのメソッドに移動します。

于 2012-06-21T12:37:43.470 に答える