对于将自定义删除器与 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); });
在我的清理方法中,我必须删除 T 吗?这样做总是安全的吗?
if (nullptr != T) delete T;
如果 cleanup() 可以抛出异常会发生什么?在某些情况下我可以让它逃脱范围,还是应该总是阻止它?
我的 ResourceManager 不依赖于我正在使用的跟踪库,因此我选择了调用者可以通过其构造函数提供的回调,并将在 release 方法中调用该回调。所以我的 Release 看起来像这样:
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; } }
这是一种合理的设计方法吗?