我有一个类Foo
的示例,它将被传递一个指向依赖对象的智能指针。这可能是一个unique_ptr
,如果调用者想要将对象的所有权转移到Foo
示例,或者如果调用者想要与Foo
示例和其他东西共享对象,则使用shared_ptr
。也许有一天它甚至会接受一个weak_ptr
,这样它就可以使用一个共享对象,只要它存在(编辑:但让我们忽略weak_ptr
,它显然使事情复杂化)。
我的问题是,以这种方式管理通用智能指针的惯用方法是什么?
想到的一个想法是使用shared_ptr
存储,并重载函数来加载它:
#include <iostream>
#include <memory>
class Bar {};
class Foo {
public:
void store(std::unique_ptr<Bar> p) { p_ = std::move(p); }
void store(std::shared_ptr<Bar> p) { p_ = std::move(p); }
// void store(std::weak_ptr<Bar> p) { p_ = p.lock(); } // don't worry about weak_ptr
private:
std::shared_ptr<Bar> p_; // a shared_ptr can store a unique_ptr, but irreversibly
};
int main() {
Foo f {};
// pass ownership of ub to f
auto ub = std::make_unique<Bar>();
f.store(std::move(ub));
// create shared ownership of sb, share with f
auto sb = std::make_shared<Bar>();
f.store(sb);
}
我想另一种方法是使用模板化的类,在编译时确定存储类型,但在我的例子中,我需要Foo
示例在运行时接受两个指针中的任何一个。此外,一旦指针存储为shared_ptr
,就不可能将其返回到unique_ptr
。
有没有比两次重载和转换为存储的shared_ptr
更好的方法?
我将尝试在下面重新表述我的问题,以使我想做的事情更清楚。不幸的是,这部分现在是一个“设计问题”,因此不能在SO的问题中提出。
我有一个脚本驱动的系统,它创建Object
s层次结构的属性-想想3D对象与相关材料。(树),创建材质并与这些对象关联。有些材质由单个对象单独拥有,有些在多个对象之间共享,有些可能是对其他材质的弱引用(如果有帮助,放弃这个要求,我更关心的是唯一/共享所有权)。
这些材料是用工厂函数创建的,它当前返回一个unique_ptr<Material>
。我选择这个是因为Scott Meyers认为它是从工厂函数返回的最通用的类型,因为它不需要工厂函数知道任何最终的所有权策略。工厂函数的调用者可以将这个unique_ptr
更改为任何其他类型。例如shared_ptr
甚至weak_ptr
,这取决于它打算如何处理此材料的所有权。
然后,它被传递给一个Object,由调用者决定该Object将如何管理此材质。也许它将作为唯一的所有者,也许它将在多个Object之间共享。因此,Object需要能够接受并存储unique_ptr
或shared_ptr
。一旦它有了这个指针,它实际上并不关心它是什么。它实际上只是为了在对象被销毁后进行材质清理。
评论表明这是一种不寻常的模式--如果是这样,我很想听到可能实现同样事情的替代设计--我可以想象它可以被描述为“注入到另一个对象中的堆分配工厂创建的依赖关系的生命周期管理”。
1条答案
按热度按时间qq24tv8q1#
我会为此写一个 Package 器,可以处理任何这些指针类型。注意,在你的例子中,弱指针的初始化是不正确的,因为它会抓住资源并防止它被破坏。这感觉不像是可预测的行为。
这里有一个可以处理所有这些指针类型的实现,使它们只是表现为“指针”。
这就是你如何使用它:
在编译器资源管理器上查看live demo。