これが私がそれを行う方法です。
まず第一に、factory
クラスは、インスタンス化するオブジェクトへの監視ポインターのみを保持します。このようにして、オブジェクトへの所有参照が存在しない場合、オブジェクトをキューに入れることなく、オブジェクトはすぐに削除されます。
次に、factory
クラスは、インスタンス化するオブジェクトへの共有ポインターを返し、それらの共有ポインターはカスタム デリーターを指定して、破棄時にファクトリのマップから削除されたオブジェクトを登録解除します。
インスタンス化するオブジェクトに、ID を引数として受け取るコンストラクターと、ID を返す関数があると仮定するとget_id()
、ファクトリ クラスのコードは次のようになります。
#include <memory>
#include <unordered_map>
#include <functional>
using namespace std;
using namespace std::placeholders;
template<typename T>
class factory
{
public:
shared_ptr<T> get_instance(int id)
{
auto i = m_map.find(id);
if (i == m_map.end())
{
return create(id);
}
else
{
shared_ptr<T> p = i->second.lock();
if (p == nullptr)
{
p = create(id);
}
return p;
}
}
shared_ptr<T> create_instance()
{
shared_ptr<T> p = create(nextId);
nextId++;
return p;
}
void unregister(T* p)
{
int id = p->get_id();
m_map.erase(id);
delete p;
}
private:
shared_ptr<T> create(int id)
{
shared_ptr<T> p(new T(id), bind(&factory::unregister, this, _1));
m_map[id] = p;
return p;
}
unordered_map<int, weak_ptr<T>> m_map;
int nextId = 0;
};
そして、それはあなたがそれを使用する方法です:
struct A
{
A(int id) : _id(id) { }
int get_id() const { return _id; }
int _id;
};
int main()
{
factory<A> f;
{
shared_ptr<A> pA = f.get_instance(5);
shared_ptr<A> pB = pA;
// ...
// The object with ID 5 will go out of scope and get unregistered
}
shared_ptr<A> pA = f.get_instance(3);
shared_ptr<A> pB = f.get_instance(3); // This will return the existing object
//
// Instance with ID 3 will go out of scope and get unregistered
}