首页 > 解决方案 > 在分配新版本资源时,在 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()通话,则资源可能正在使用大量内存或磁盘空间,并且在没有首先重置的情况下重新分配可能会在较小的计算机上导致问题。要么,要么资源被锁定,因此在显式释放之前无法重新分配。

是否有一种模式/算法/某种东西可以以更清洁的方式处理这种情况?

标签: c++algorithmdesign-patternsresources

解决方案


我基本上看到了两种方法来解决这个问题。第一种是将重置分配序列包装到一个函数中,并且从不直接分配。我可能会这样做

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 智能指针的其他代码交互也会很烦人,这将是一个主要的重构过程。但是你不能通过意外调用一个作业来搞砸它(至少可能不会)。

另请注意,标准库确实按此顺序有意重置,以便在新分配抛出时我们不会删除旧资源。


推荐阅读