您当前位置:地名问答 > 中国 > 浙江 > 杭州 > 西湖区 > 断桥残雪 > 断桥残雪地名

CString需要注意的地方(2)

更新:2017-08-18 01:51断桥残雪地名

导读:其中前面 sizeof(CstringData) 个 BYTE 是用来存放 CstringData 信息的。后面的 nLen + 1 个 TCHAR 才是真正用来存放字符串的,多出来的一个用来存放 /0 。 Cstring 中所

   其中前面sizeof(CstringData)BYTE 是用来存放CstringData 信息的。后面的nLen1TCHAR 才是真正用来存放字符串的,多出来的一个用来存放’/0’

Cstring 中所有的operations 的都是针对这个缓冲区的。比如LPTSTR CString::GetBuffer(int nMinBufLength) ,它的实现方法是:

首先通过Cstring::GetData() 取得CstringData 对象的指针。该指针是通过存放字符串的指针m_pchData 先后偏移sizeof(CstringData) ,从而得到了CstringData 的地址。然后根据参数nMinBufLength 给定的值重新实例化一个CstringData 对象,使得新的对象里的字符串缓冲长度能够满足nMinBufLength

然后在重新设置一下新的CstringData 中的一些描述值。最后将新CstringData 对象里的字符串缓冲直接返回给调用者。

这些过程用C++ 代码描述就是:

   if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)

   {

               // we have to grow the buffer

               CStringData* pOldData = GetData();

               int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it

               if (nMinBufLength < nOldLen)

                           nMinBufLength = nOldLen;

               AllocBuffer(nMinBufLength);

               memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));

               GetData()->nDataLength = nOldLen;

               CString::Release(pOldData);

   }

   ASSERT(GetData()->nRefs <= 1);

    // return a pointer to the character storage for this string

   ASSERT(m_pchData != NULL);

   return m_pchData;

   很多时候,我们经常的对大批量的字符串进行互相拷贝修改等,Cstring 使用了CopyBeforeWrite 技术。使用这种方法,当利用一个Cstring 对象a 实例化另一个对象b 的时候,其实两个对象的数值是完全相同的,但是如果简单的给两个对象都申请内存的话,对于只有几个、几十个字节的字符串还没有什么,如果是一个几K 甚至几M 的数据量来说,是一个很大的浪费。

因此Cstring 在这个时候只是简单的将新对象b 的字符串地址m_pchData 直接指向另一个对象a 的字符串地址m_pchData 。所做的额外工作是将对象a 的内存应用CstringData:: nRefs 加一。

CString::CString(const CString& stringSrc)

{

               m_pchData = stringSrc.m_pchData;

               InterlockedIncrement(&GetData()->nRefs);

}

    这样当修改对象a 或对象b 的字符串内容时,首先检查CstringData:: nRefs 的值,如果大于一( 等于一,说明只有自己一个应用该内存空间) ,说明该对象引用了别的对象内存或者自己的内存被别人应用,该对象首先将该应用值减一,然后将该内存交给其他的对象管理,自己重新申请一块内存,并将原来内存的内容拷贝过来。

其实现的简单代码是:

void CString::CopyBeforeWrite()

{

   if (GetData()->nRefs > 1)

   {

               CStringData* pData = GetData();

               Release();

               AllocBuffer(pData->nDataLength);

memcpy(m_pchData, pData->data(),

             (pData- >nDataLength+1)*sizeof(TCHAR));

   }

}

其中Release 就是用来判断该内存的被引用情况的。

void CString::Release()

{

   if (GetData() != _afxDataNil)

   {

               if (InterlockedDecrement(&GetData()->nRefs) <= 0)

                           FreeData(GetData());

   }

}

很赞哦! (82)

相关文章