我一直在尝试使用智能指针来升级现有的应用程序,并且我正在尝试克服一个难题。在我的应用程序中,我有一个对象缓存,例如,我们称它们为书籍。现在,书籍的缓存是通过 ID 请求的,如果它们在缓存中,则返回它们,如果不在缓存中,则从外部系统请求对象(操作缓慢)并将其添加到缓存中。一旦进入缓存,应用程序中就可以打开许多窗口,每个窗口都可以引用该书。在以前版本的应用程序中,程序员必须维护 AddRef 和 Release,当每个使用 Book 对象的窗口关闭时,最终的 Release(在缓存管理器上)将从缓存中删除该对象并删除该对象。
您可能已经在这里发现了链条中的薄弱环节,当然是程序员记得调用 AddRef 和 Release。现在我已经转向智能指针(boost::intrusive),我不再需要担心调用 AddRef 和 Release。然而这会导致一个问题,缓存具有对该对象的引用,因此当最终窗口关闭时,缓存不会收到其他人持有该引用的通知。
我的第一个想法是定期遍历缓存并清除引用计数为 1 的对象。我不喜欢这个主意,因为这是 N 级行动,感觉不对。我想出了一个回调系统,它更好,但并不出色。我已经包含了回调系统的代码,但是我想知道是否有人有更好的方法来做到这一点?
class IContainer
{
public:
virtual void FinalReference(BaseObject *in_obj)=0;
};
class BaseObject
{
unsigned int m_ref;
public:
IContainer *m_container;
BaseObject() : m_ref(0),m_container(0)
{
}
void AddRef()
{
++m_ref;
}
void Release()
{
// if we only have one reference left and we have a container
if( 2 == m_ref && 0 != m_container )
{
m_container->FinalReference(this);
}
if( 0 == (--m_ref) )
{
delete this;
}
}
};
class Book : public BaseObject
{
char *m_name;
public:
Book()
{
m_name = new char[30];
sprintf_s(m_name,30,"%07d",rand());
}
~Book()
{
cout << "Deleting book : " << m_name;
delete [] m_name;
}
const char *Name()
{
return m_name;
}
};
class BookList : public IContainer
{
public:
set<BookIPtr> m_books;
void FinalReference(BaseObject *in_obj)
{
set<BookIPtr>::iterator it = m_books.find(BookIPtr((Book*)in_obj));
if( it != m_books.end() )
{
in_obj->m_container = 0;
m_books.erase( it );
}
}
};
namespace boost
{
inline void intrusive_ptr_add_ref(BaseObject *p)
{
// increment reference count of object *p
p->AddRef();
}
inline void intrusive_ptr_release(BaseObject *p)
{
// decrement reference count, and delete object when reference count reaches 0
p->Release();
}
} // namespace boost
干杯
富有的
我从未使用过 boost::intrusive 智能指针,但如果您使用shared_ptr 智能指针,则可以使用weak_ptr 对象作为缓存。
当系统决定释放其内存时,这些weak_ptr指针不算作引用,但只要该对象尚未被删除,就可以用来检索shared_ptr。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)