【发布时间】:2015-02-28 20:42:15
【问题描述】:
我仍然对使用带有 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; } }
这是一种合理的设计方法吗?
【问题讨论】:
-
“这是一种合理的设计方法吗?” - 否。
Release可以在对象销毁的上下文中调用。由于异常可能已经在进行中,因此在此阶段发生的异常可能是一个主要问题。 -
但是将所有内容包装在 try catch 块中并将 Callback 设置为 nothow() 会好吗?
标签: c++ shared-ptr resource-management