我对使用自定义删除器与shared_ptr的正确方法仍然有些困惑。我有一个ResourceManager类来跟踪资源分配,并修改了其接口以支持通过使Release方法私有化和让Allocate方法返回ResourceHolder来自动释放已使用的资源:
// ResourceManager.cpp:
public:
ResourceHolder<Resource> Allocate(args);
private:
void Release(Resource*);
我实现的ResourceHolder类如下:
// ResourceHolder.h
template <typename T>
class ResourceHolder
{
public:
ResourceHolder(
_In_ T* resource,
_In_ const std::function<void(T*)>& cleanupFunction)
: _cleanupFunction(cleanupFunction)
, _resource(resource, [&](T* resource)
{
cleanup(resource);
}) // Uses a custom deleter to release the resource.
{
}
private:
std::function<void(T*)> _cleanupFunction;
std::shared_ptr<T> _resource;
};
// ResourceManager::Allocate()
...
return ResourceHolder<Resource>(new Resource(),[this](Resource* r) { Release(r); });
In my cleanup method, do I have to delete T? Is it always safe to do it?
if (nullptr != T) delete T;
What happens if cleanup() can throw an exception? Can I let it escape the scope under some circumstances, or should I always prevent it?
My ResourceManager does not have a dependency on a tracing library I'm using, so I opted for a callback which a caller can provide through its constructor, and which will get called in the release method. So my Release looks something like this:
void Release(Resource* r) { shared_ptr<std::Exception> exc = nullptr; try { // Do cleanup. } catch(Exception* ex) { exc.reset(ex); } if (nullptr != r) delete r; // Is it now safe to throw? if (nullptr != m_callback) m_callback(args, exc); } void Callback(args, shared_ptr<std::Exception> ex) { // Emit telemetry, including exception information. // If throwing here is ok, what is the correct way to throw exception here? if (nullptr != ex) { throw ex; } }
Release
可以在对象销毁的上下文中被调用。由于异常可能已经在进行中,因此在此阶段发生异常可能会导致严重问题。 - Captain Obvlious