|
CString Class Research (2)
3. CString Data Buffer
CString use CStringData structure as a buffer to store data and other information.
struct CStringData
{
long nRefs; // reference count
int nDataLength; // length of data (including terminator)
int nAllocLength; // length of allocation
// TCHAR data[nAllocLength]
TCHAR* data() // TCHAR* to managed data
{ return (TCHAR*)(this+1); }
};
A CString Data Buffer (CStringData)
CStringData::data() will return to actually data address.
CString::m_pchData member variable is a pointer of actually data address.
CString::GetData() return CStringData, point to the buffer, include header and actually data.
_AFX_INLINE CStringData* CString::GetData() const
{ ASSERT(m_pchData != NULL); return ((CStringData*)m_pchData)-1; }
CString::operator LPCTSTR() return the address of m_pchData.
_AFX_INLINE CString::operator LPCTSTR() const
{ return m_pchData; }
CString::GetBuffer() function will do following process:
create a new buffer;
copy old value to new buffer;
dispose old buffer;
return new buffer;
But if the CString have been referenced (the data buffer is not point to _afxPchNil), and the allocate length is bigger than required, It needn’t allocate new buffer, It will return current buffer only.
For example:
CString str1;
char * buf;
buf = str1.GetBuffer(10);
Before GetBuffer() function is invoked, the address of str1 is 0x0012f6f8, the address of str1.m_pchData is 0x5f4c4b14 (should be system defined “null” buffer, _afxPchNil).
And after GetBuffer() function is invoked, the address of str1 is 0x0012f6f8, the address of str1.m_pchData is 0x004213fc, Changed!.
So that, the LPCTSTR() operator and GetBuffer() is different, LPCTSTR() operator will not create new buffer but return the current buffer.
And other example:
CString str1(“this buffer is big enough);
char * buf;
buf = str1.GetBuffer(10);
In this example, the address of data buffer is not changed.
The following diagram is showing the format of system defined “null” buffer and value:
CString::ReleaseBuffer() function will update the “header” filed of CStringData.
void CString::ReleaseBuffer(int nNewLength)
{
CopyBeforeWrite(); // just in case GetBuffer was not called
if (nNewLength == -1)
nNewLength = lstrlen(m_pchData); // zero terminated
ASSERT(nNewLength <= GetData()->nAllocLength);
&n [1] [2] 下一页 |