c++ - 在分配新版本资源时,在 C++ 中处理复杂资源指针的做法是什么?
问题描述
在我现在的大部分编程中,我把所有东西都放在一个智能指针中,然后就忘了它。资源在 99.9% 的时间内得到妥善管理。它真的很棒,而且比垃圾收集机制更好。
然而,有时,智能指针持有的资源需要显式释放,然后我们才能重新分配它的新实例。像这样的东西:
r = std::make_shared<my_resource>(with_this_id);
r->do_work();
...
r->do_more_work();
...
r->do_even_more_work();
r.reset();
r = std::make_shared<my_resource>(with_this_id);
...
如果我错过了r.reset()
通话,则资源可能正在使用大量内存或磁盘空间,并且在没有首先重置的情况下重新分配可能会在较小的计算机上导致问题。要么,要么资源被锁定,因此在显式释放之前无法重新分配。
是否有一种模式/算法/某种东西可以以更清洁的方式处理这种情况?
解决方案
我基本上看到了两种方法来解决这个问题。第一种是将重置分配序列包装到一个函数中,并且从不直接分配。我可能会这样做
template<typename T, typename ...Args>
void reset_and_assign(std::shared_ptr<T> &ptr, Args ... &&args) { //in-out parameter to avoid copy since you cannot rvo on a parameter
ptr.reset();
ptr.reset(new T(std::forward<Args> args...));
}
这非常容易和快速,但它不会让你避免不小心直接调用作业,如果你继续使用,我看不出有办法做到这一点shared_ptr
。
另一种选择是编写一个包装器,它只shared_ptr
转发大多数函数调用、更改reset
和分配,以便它首先解除分配,然后创建新资源。这需要做一些工作,而且很容易在其中产生错误(特别是如果您尝试为自己保存一些构造函数而弄乱了一些通用引用)。与使用 std 智能指针的其他代码交互也会很烦人,这将是一个主要的重构过程。但是你不能通过意外调用一个作业来搞砸它(至少可能不会)。
另请注意,标准库确实按此顺序有意重置,以便在新分配抛出时我们不会删除旧资源。
推荐阅读
- certificate - 证书上的“签名算法”到底是什么意思?使用哪种签名算法来签署我的证书?
- c++ - 不能用作函数,返回前的最后一行是错误
- android - 如何配置 Android Gradle 项目以过滤资源?
- javascript - 设置状态的新 Promise 接收箭头函数
- computer-vision - 如何使用 Viola Jones 算法将人脸检测为感兴趣区域并将其裁剪到矩形框?
- python - 加入列表最后几个元素并将新加入的项目附加回列表的最快和 Pythonic 方式
- python - python - 如何在python中拆分不包含分隔符的连接字符串?
- javascript - 如何正确过滤数组
- c# - Unity - 错误 CS106:类型“分数”不包含 scoreUp 的定义
- python - 异步 websocket 代码但一直以预期的方式工作?