I'm working on a garbage-collection mechanism for a family of objects in one of my projects. What I want to have is allocate these objects dynamically with new
and never having to call delete
.
This is possible by overloading operator new
to call into a specialized allocator object that implements GC for these objects (triggering collection when too much memory has been allocated). However, I have a problem: the user can still just do delete
on these objects, and I don't want that.
Making operator delete
private is problematic because of the way C++ handles failures in construction - if operator new
is public, operator delete
should be too. The alternative that's sometimes suggested is just make both operator new
and operator delete
private and only expose factory creation methods to the user. I can do this, but it feels less clean and requires extra code to开发者_如何学Go write.
EDIT: Another approach is make operator delete
empty (or throw an exception). Then, to actually release the objects my GC will call the destructor explicitly and then release the memory with the global ::operator delete
.
Any other ideas?
Personally I think the idea of making both private and using the factory is the cleaner approach. Using new but not delete (or assigning to smart pointer) is going to confuse a lot of maintainers of the code.
If you can indicate that a pointer comes from a GC collected factory (or is owned by a GC collected factory) then it will make the code less confusing to maintain. By using a factory you are explicitly stating that the GC factory is the owner and thus should maintain the lifespan of the object:
class GCFactory
{
public:
template<T, P1>
T& createGCObject(P1 const& p1) // Or return by pointer.
{
T* result = new T(p1);
// Do stuff to register with garbage collector.
// Then return object (I like reference) but I have not studied the
// problem that hard so may be in-appropriate.
return * result;
}
template<T, P1, P2>
T& createGCObject(P1 const& p1, P2 const& p2)
{
T* result = new T(p1, p2);
// Do stuff to register with garbage collector.
return * result;
}
template<T, P1, P2, P3>
T& createGCObject(P1 const& p1, P2 const& p2, P3 const& p3)
{
T* result = new T(p1, p2, p3);
// Do stuff to register with garbage collector.
return * result;
}
};
Overload delete as a no-op. (more characters needed)
boost::shared_ptr<Type> ptr = boost::make_shared<Type>();
You never call new, you never call delete.
Why reinvent the wheel? Smart pointers really are the way to go.
精彩评论