0

コードで次の宝石を発見しました (例は非常に単純化されていますが、ロジックは同じです)。

template <class T>
class garbage_bin
{
private:
    garbage_bin<T>(void)
    {
    }
   static garbage_bin<T>* pinstance;
public:
   static garbage_bin<T>& instance()
   {
       if(pinstance == NULL)
       {
           pinstance = new garbage_bin<T>();
       }

       return *pinstance;
   }

   void empty()
   {
       for(size_t i=0; i<items.size(); i++)
       {
           free (items[i]);
       }
   }

   void throwIn(T item)
   {
       items.push_back(item);
   }

   vector<T> items;
};

そしてコードのどこかに(これはほんの一例です...このようなものは何千もあります):

char* r = strdup(src);
garbage_bin<char*>::instance().throwIn(r);

その後、コードのどこかで、終了の直前に...

garbage_bin<char*>::instance().empty();
garbage_bin<molecules*>::instance().empty();
garbage_bin<CDatabaseUsers*>::instance().empty();

等々 ...

ご覧のとおり、これはガベージ ビン クラスを実装します。このクラスでは、あらゆる種類のオブジェクトを「投入」できます。後の段階でメモリ リークを回避するために、ガベージ ビンを「空」にします。しかし、ここで大きなボトルネックが発生します。これが適切に機能するためには、このガベージ ビンがインスタンス化されたすべてのクラスを把握して、それらを空にする必要があります...

私が考えていた最も直接的な解決策はtypeid、インスタンス化の呼び出しのマップを作成し、名前に を割り当てることgarbage_bin<T>::instance()ですが、古代のコンパイラはこのアプローチが気に入らないと判断しました。

明らかに、コードを検索してすべてのテンプレート化を見つけることができますが、疑問に思っています...これを行う簡単な方法はありますか?

4

3 に答える 3

0

削除するもののレジストリを追加できます。

Registry registry;

// ...

if (pinstance == NULL)
{
     pinstance = new garbage_bin<T>();
     registry.add<T>();
}

// ...

registry.clear_all();

例えば:

class Registry
{
     struct Base
     { 
         virtual ~Base() {}
         virtual void clear() = 0;
     };

     template <typename T> struct Derived : Base
     {
         virtual void clear() { garbage_bin<T*>::instance().empty(); }
     };

     std::vector<std::unique_ptr<Base>> targets;

public:
     void clear_all() { for (auto & p : targets) { p->clear(); } }

     template <typename T> void add()
     {
          targets.emplace_back(new Derived<T>);
     }
};
于 2013-11-07T11:50:59.270 に答える
0

むしろ(または、多分) に置き換えたいと思いgarbage_bin<T>ます。std::vector<std::unique_ptr<T>>std::vector<std::shared_ptr<T>>

インターフェースを制限したい場合はgarbage_bin<T>、 のラッパーとして再実装してstd::vector<std::unique_ptr<T>>ください。この方法では、とemptyのデストラクタが自分自身の後にクリーンアップするため、おそらくメソッドは必要ありません。ただし、破棄する前にビンを空にしたい場合は、 を呼び出すだけで実装します。std::vectorstd::unique_ptremptystd::vector::clear

これが最も簡単なことではないことは理解していますが(OPには変更する場所が「数千」あると書かれているため)、この悪い設計のリファクタリングが明らかに必要です。

于 2013-11-07T11:53:34.107 に答える