在如今的大多数编程中,我每天都将所有内容放在一个智能指针中,而忽略了它。 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智能指针的代码进行交互也将很烦人,这将是一个主要的重构过程。但是您不能通过不小心调用一个分配(至少可能不是)来弄乱它。还要注意,标准库确实会按此顺序有意重置,这样,如果抛出新分配,我们就不会删除旧资源。