C++ 智能指针/编码模式的名称
最近,我经常遇到需要类似于此数据结构的东西的情况 限制:C++03标准C++ 智能指针/编码模式的名称,c++,design-patterns,boost,qt4,smart-pointers,C++,Design Patterns,Boost,Qt4,Smart Pointers,最近,我经常遇到需要类似于此数据结构的东西的情况 限制:C++03标准 有几个节点类,其中每个节点持有对同一个“数据”(类、结构,无论什么-动态分配)实例的节点引用(思考共享的) 还有一个“Root”或“master”节点/类,它持有对相同“数据”的RootDataRef引用(这一次,考虑弱的ptr) 当所有节点被销毁时,数据也被销毁,RootDataRef被设置为0/NULL。也就是说,NodeDataRef的行为类似于shared\u ptr和RootDataRef的行为类似于weak\u
节点
类,其中每个节点
持有对同一个“数据
”(类、结构,无论什么-动态分配)实例的节点引用(思考共享的
)李>
还有一个“Root
”或“master”节点/类,它持有对相同“数据
”的RootDataRef
引用(这一次,考虑弱的ptr
)
当所有节点
被销毁时,数据
也被销毁,RootDataRef
被设置为0
/NULL
。也就是说,NodeDataRef
的行为类似于shared\u ptr
和RootDataRef
的行为类似于weak\u ptr
但是根节点可以强制销毁数据,即使仍有活动的NodeDataRef
s。在这种情况下,所有指向数据的NodeDataRef
s都被设置为NULL
/0
,RootDataRef
也被设置为0
/NULL
即,弱\u ptr
可强制销毁所有链接的共享\u ptr
此模式/智能指针类型是否有名称
如何使用Boost或Qt4快速实现这一点?(“快速”表示无需编写类来维护引用列表)
此模式/智能指针类型是否有名称
据我所知,不,这不是一个具有常用名称的典型所有权模式
如何使用Boost或Qt4快速实现这一点?(“快速”表示无需编写类来维护引用列表)
对于这个用例没有预先打包的所有权策略,因为这会破坏共享所有权的观点。如果存在指向给定对象的多个共享指针,根据定义,这些共享指针必须使该对象保持活动状态。如果给我一个共享指针,这就保证了对象在我释放它之前是存在的
如果您希望一个主对象能够命令销毁指向它的对象,而不管其他对象是否持有指向它的共享指针,那么您必须想出一些单独的机制,让它命令指向该对象的共享指针的所有持有者释放它
更新:
尽管存在“黑客”解决方案可以“快速”完成这项工作,但我不建议您使用其中任何一种。这种模式非常非典型,以至于当有人阅读您的代码时(包括几个月后的您),您希望它是明显的
您的意图应该通过主对象和其他所有者之间的显式通信模式来明确,而不是隐藏在包装器、自定义删除器或其他任何东西中。您可以使用共享\u ptr
和弱\u ptr
其中T=scoped\u ptr
。假设您可以使用操作符new创建数据实例)
应使用make_shared(新数据(…))分配shared_ptr
代码>
根弱\u ptr可以通过调用root.lock().reset()
模板
结构RootHandle:public boost::weak\u ptr
{
typedef boost::弱_ptr弱_type;
typedef boost::shared_ptrstrong_type;
RootHandle(){}
RootHandle(const弱类型和impl)
:弱_型(impl){
T*get()常量
{
强_类型x=锁();
返回(x)→x->get():0;
}
无效重置()
{
强_类型x=锁();
if(x)
x->reset();
}
};
模板
结构NormalHandle:public boost::shared\u ptr
{
公众:
typedef boost::shared_ptrstrong_type;
NormalHandle(){}
NormalHandle(常量强类型和impl)
:强_类型(impl){
T*get()常量
{
boost::scoped_ptr*ppx=strong_type::get();
返回(0!=ppx)?ppx->get():0;
}
};
新NormalHandles的初始化如下所示:
normalhandlehandle1(boost::make_shared(新数据(4,3,“abc”))代码>我不知道您为什么要这样做,但这里有一个(非常)黑客的解决方案,它还需要在每次访问NodeDataRef
时运行一些额外的代码(理想情况下作为该类的方法)
与数据一起创建sentinel对象。给RootDataRef
一个拥有它的引用,给所有节点一个弱引用。然后,在每次访问NodeDataRef
之前,检查对哨兵的弱引用是否仍然有效。要强制从根目录
中删除,请删除对sentinel所拥有的引用,从而导致节点数据库中的所有弱引用无效。一种易于实现(但不是最有效)的方法是使用双共享ptr层:
共享\u ptr
根目录将有一个指向该目录的弱指针,当您需要强制销毁时,您将重置内部共享的\u ptr数据(在锁定下执行!)
所有其他节点都将正常使用它,但在使用它之前必须检查内部共享\u ptr的有效性。没有人给出特定于Qt的答案(奇怪?),因此我将对此进行分析,尽管我对共享指针类有点粗糙
似乎可以将RootDataRef
生成为一个节点,并从中派生节点。创建第一个NodeDataRef
后,将RootDataRef
降级为使用。这样,当您删除所有的NodeDataRef
s时,原始指针将被删除,而RootD将被删除
+-----+--------------+ +----+
|node0| NodeDataRef ->-------------->|data|
+-----+--------------+ +----+
+-----+--------------+ ^^ ^
|node1| NodeDataRef ->----------------+| |
+-----+--------------+ | |
+-----+--------------+ | |
|node2| NodeDataRef ->-----------------+ |
+-----+--------------+ |
|
+-----+--------------+ |
|root | RootDataRef ->-------------------+
+-----+--------------+
template <typename T>
struct RootHandle : public boost::weak_ptr< boost::scoped_ptr<T> >
{
typedef boost::weak_ptr< boost::scoped_ptr<T> > weak_type;
typedef boost::shared_ptr< boost::scoped_ptr<T> > strong_type;
RootHandle() {}
RootHandle(const weak_type& impl)
:weak_type(impl) {}
T* get() const
{
strong_type x = lock();
return (x) ? x->get() : 0;
}
void reset()
{
strong_type x = lock();
if (x)
x->reset();
}
};
template <typename T>
struct NormalHandle : public boost::shared_ptr< boost::scoped_ptr<T> >
{
public:
typedef boost::shared_ptr< boost::scoped_ptr<T> > strong_type;
NormalHandle() {}
NormalHandle(const strong_type& impl)
:strong_type(impl) {}
T* get() const
{
boost::scoped_ptr<T>* ppx = strong_type::get();
return (0 != ppx) ? ppx->get() : 0;
}
};