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

1

垃圾桶垃圾桶!

class garbage_bin_base;

class garbage_bin_bin {
public:
    void throwIn(garbage_bin_base* rubbish) { items.push_back(rubbish); }
    void empty() { for (auto item: items) item->empty(); }
private:
    vector<garbage_bin_base*> items;
};

class garbage_bin_base {
public:
    virtual empty() = 0;
    garbage_bin_base() { garbage_bin_bin::instance().throwIn(this); }
};

template <typename T>
class garbage_bin : public garbage_bin_base {
};
于 2013-11-07T11:50:00.777 回答
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>>. 这样,您可能不需要该方法,因为andempty的析构函数会自行清理。但是,如果您想在销毁之前清空 bin,则只需调用.std::vectorstd::unique_ptremptystd::vector::clear

我知道这并不是最简单的事情(因为 OP 说有“数千”个地方需要更改),但显然需要对这种糟糕的设计进行重构。

于 2013-11-07T11:53:34.107 回答