CString是否使用了引用计数

89 篇文章 5 订阅

Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源

 

问题: CString是否使用了引用计数?

答案是肯定的。平常使用的时候确实没有查觉这方面,包括我们可以把CString强制转为TCAHR*来使用,效果也都正常。

 

CString强制转为TCAHR*为什么能正常,原因是什么呢?

原因是单纯从数据结构上来看,它仅有一个变量: m_pszData

 

但它动态申请的内存结构是这样的

 [CStringData结构][存储字符串]

而m_pszData指向[存储字符串]

 

如何来定位CStringData,是这样定位的

CStringData* GetData() const throw()

{

         return( reinterpret_cast< CStringData* >( m_pszData )-1 );

}

我觉得这个非常巧妙,通过m_pszData往前回退sizeof(CStringData)来查找到CStringData的数据。

 

 

至于引用计数、字符段长度、申请长度等相关的数据结构,定义在CStringData结构中

struct CStringData

{

         IAtlStringMgr* pStringMgr;  // String manager for this CStringData

         int nDataLength;  // Length of currently used data in XCHARs (not including terminating null)

         int nAllocLength;  // Length of allocated data in XCHARs (not including terminating null)

         long nRefs;     // Reference count: negative == locked

         // XCHAR data[nAllocLength+1]  // A CStringData is always followed in memory by the actual array of character data

 

         void* data() throw()

         {

                   return (this+1);

         }

 

         void AddRef() throw()

         {

                   ATLASSERT(nRefs > 0);

                   _AtlInterlockedIncrement(&nRefs);

         }

         bool IsLocked() const throw()

         {

                   return nRefs < 0;

         }

         bool IsShared() const throw()

         {

                   return( nRefs > 1 );

         }

         void Lock() throw()

         {

                   ATLASSERT( nRefs <= 1 );

                   nRefs--;  // Locked buffers can't be shared, so no interlocked operation necessary

                   if( nRefs == 0 )

                   {

                            nRefs = -1;

                   }

         }

         void Release() throw()

         {

                   ATLASSERT( nRefs != 0 );

 

                   if( _AtlInterlockedDecrement( &nRefs ) <= 0 )

                   {

                            pStringMgr->Free( this );

                   }

         }

         void Unlock() throw()

         {

                   ATLASSERT( IsLocked() );

 

                   if(IsLocked())

                   {

                            nRefs++;  // Locked buffers can't be shared, so no interlocked operation necessary

                            if( nRefs == 0 )

                            {

                                     nRefs = 1;

                            }

                   }

         }

};

 

__interface IAtlStringMgr

{

public:

    // Allocate a new CStringData

    CStringData* Allocate( int nAllocLength, int nCharSize ) throw();

    // Free an existing CStringData

    void Free( CStringData* pData ) throw();

    // Change the size of an existing CStringData

    CStringData* Reallocate( CStringData* pData, int nAllocLength, int nCharSize ) throw();

    // Get the CStringData for a Nil string

    CStringData* GetNilString() throw();

    IAtlStringMgr* Clone() throw();

};

 

 

注意:

std::auto_ptr是独占的,它没有使用引用计数

它的数据结构中的变量只有一个

_Ty *_Myptr;     // the wrapped object pointer

 

std::shared_ptr采用了引用计数

它的数据结构中的变量有两个

    _Ty *_Ptr;

    _Ref_count_base *_Rep;

 

 

Boost库中的shared_ptr采用了引用计数年

它的数据结构中的变量有两个

    T * px;            // contained pointer

    count_type * pn;   // ptr to reference counter

 

引用计数用于了内存的重用,但对于写操作,肯定是需要重请申请信息的,这种技术称为Copy on Write(写时再Copy)

 

Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春夜喜雨

稀罕你的喜欢!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值