shared_ptr でカスタムのデリータを使用する適切な方法について、私はまだ少し混乱しています。リソース割り当てを追跡する ResourceManager クラスがあり、Release メソッドを非公開にし、ResourceHolder を返す Allocate メソッドを作成することで、使用済みリソースの自動解放をサポートするようにそのインターフェイスを変更しました。
// 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 は、私が使用しているトレース ライブラリに依存していません。そのため、呼び出し元がコンストラクターを介して提供でき、リリース メソッドで呼び出されるコールバックを選択しました。したがって、私のリリースは次のようになります。
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; } }
これは健全な設計アプローチですか?