我一直致力于用引用计数指针替换原始指针,这些指针仅公开底层指针的 const 版本。我的目标是减少内存使用量(以及不必要地构造和破坏复杂对象所花费的时间),而不会让自己陷入任何代码都可以访问它不拥有的内存的情况。我知道引用计数存在循环引用问题,但我的代码永远不应该造成这种情况。
要求 const 性是有效的,因为我使用的系统中的类通常不公开非常量成员,并且您必须调用其上的方法来返回由更改产生的新对象,而不是更改对象。这可能是一种设计模式,但我不知道它的名字。
当我有一个方法返回指向其类型的对象(有时是其本身)的指针时,我的问题就出现了。以前它看起来像这样:
Foo * Foo::GetAfterModification( const Modification & mod ) const
{
if( ChangesAnything( mod ) )
{
Foo * asdf = new Foo;
asdf.DoModification( mod );
return asdf;
}
else
return this;
}
我看不出有什么好方法让这个返回成为智能指针。天真的方法类似于 return CRcPtr< Foo >( this )
,但这打破了所有权语义,因为我返回的内容和以前拥有该对象的人现在都认为他们拥有所有权,但彼此不了解。唯一安全的做法是 return CRcPtr< Foo >( new Foo( *this ) )
,但这违背了我限制不必要的内存使用的意图。
是否有某种方法可以安全地返回智能指针而不分配任何额外的内存?我怀疑不存在。如果有,如果该对象已分配在堆栈上,它将如何工作? This question看起来相关,但并不相同,因为他可以让他的函数将原始指针作为参数,并且因为他正在使用 boost 库。
作为引用,我的家庭滚动智能指针实现如下。我确信它可以更强大,但它比依赖于随处可用的 boost 或 tr1 更便携,并且在这个问题之前它对我来说效果很好。
template <class T>
class CRcPtr
{
public:
explicit CRcPtr( T * p_pBaldPtr )
{
m_pInternal = p_pBaldPtr;
m_iCount = new unsigned short( 1 );
}
CRcPtr( const CRcPtr & p_Other )
{ Acquire( p_Other ); }
template <class U>
explicit CRcPtr( const CRcPtr< U > & p_It )
{
m_pInternal = dynamic_cast< T * >( p_It.m_pInternal );
if( m_pInternal )
{
m_iCount = p_It.m_iCount;
(*m_iCount)++;
}
else
m_iCount = new unsigned short( 1 );
}
~CRcPtr()
{ Release(); }
CRcPtr & operator=( const CRcPtr & p_Other )
{
Release();
Acquire( p_Other );
}
const T & operator*() const
{ return *m_pInternal; }
const T * operator->() const
{ return m_pInternal; }
const T * get() const
{ return m_pInternal; }
private:
void Release()
{
(*m_iCount)--;
if( *m_iCount == 0 )
{
delete m_pInternal;
delete m_iCount;
m_pInternal = 0;
m_iCount = 0;
}
}
void Acquire( const CRcPtr & p_Other )
{
m_pInternal = p_Other.m_pInternal;
m_iCount = p_Other.m_iCount;
(*m_iCount)++;
}
template <class U>
friend class CRcPtr;
T * m_pInternal;
unsigned short * m_iCount;
};
template <class U, class T>
CRcPtr< U > ref_cast( const CRcPtr< T > & p_It )
{ return CRcPtr< U >( p_It ); }
编辑:感谢您的回复。我希望避免使用 boost 或 tr1,但我认识到不使用经过良好测试的库通常是不明智的。我相当确定我所实现的不与 std::auto_ptr 类似,而是与 tr1::shared_ptr 类似,只是它只公开了内部指针的 const 版本,并且缺少一些正式版的功能。我真的很想避免像 Gian Paolo 提出的那样的侵入性方案。我知道我的实现不是线程安全的,但这是一个单线程应用程序。
最佳答案
查看 Boost 的源代码 shared pointers 。如果您从 enable_shared_from_this<T>
派生一个类,然后您可以调用 shared_from_this()
成员函数来做这类事情。
关于c++ - C++ 中带有 "this"的智能指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/592728/