浅析CString内部实现机制

CString是微软程序员的偏爱,用不好也会让你很头疼,又爱又恨啊。
主要实现在三个文件中atlstr.h cstringt.h atlsimpstr.h, atlsimpstr.h负责最基本的设计,cstringt.h则负责一些高级函数的实现,atlstr.h负责最后的封装。
如果在非MFC工程中使用CString的,主要#include <atlstr.h> 就足够了。


看到这段代码,挺有意思^0^
template< typename BaseType = char >
class ChTraitsBase
{
public:
    typedef char XCHAR;
    typedef LPSTR PXSTR;
    typedef LPCSTR PCXSTR;
    typedef wchar_t YCHAR;
    typedef LPWSTR PYSTR;
    typedef LPCWSTR PCYSTR;
};

template<>
class ChTraitsBase< wchar_t >
{
public:
    typedef wchar_t XCHAR;
    typedef LPWSTR PXSTR;
    typedef LPCWSTR PCXSTR;
    typedef char YCHAR;
    typedef LPSTR PYSTR;
    typedef LPCSTR PCYSTR;
};
把传进来的模板参数定义为X,另一种字符则为Y.


CString最基本的血液来自CSimpleStringT,在CSimpleStringT里面我们可以看到CString最核心的设计理念:
                                                                                        
                                                                                      
 ---------------------------------------------------------------------------------
 |  pStringMgr  | nDataLength | nAllocLength | nRefs | m_pszData[nAllocLength+1] |
 ---------------------------------------------------------------------------------
 |<-------------CStringData------------------------>|<----------buffer------------>
                                                                                                        
 如图所示,CSimpleStringT的内存前段部分是属性区用CStringData类来管理,后面的buffer则是真正的字符串存储区。
从源码中可以很清晰的看出CSimpleStringT的工作机制,也会理解为什么如果使用GetBuffer()对buffer区的值进行了修改,一定要调用ReleaseBuffer()---要对buffer区的属性进行更新啊。


在struct CStringData中很神奇的一句代码:
    void* data() throw()
    {
        return (this+1);
    }
指针加减是有另一套规则的,this+1实际上“1”代表了sizeof(this);同理 m_pchData -1 就到了CStringData内存地址了。
指针相减则是所指向的字符串的长度差。

CString设计的目标是方便、高效,这可以从源码中看出来:
如果一个CString str2是从另一个CString str1赋值过来的,那么不会马上给str2分配内存,而是直接指向str1的内存,此时,str1的nRefs要加1,当str2或者str1的取值发生改变时,才真正的给str2开辟空间。

当nRefs==0时,ReleaseBuffer()才真正的释放这块内存,否则只是nRefs--.
值得注意的是,如果buffer被Lock了(可以被Lock的前提是未被share),nRefs=-1.


看,CSimpleStringT把关键字PCXSTR都定义成operator了:
    operator PCXSTR() const throw()
    {
        return( m_pszData );
    }

      


                                                                        

另外,封装中用到了很多**TraitsOS  **TraitsCRT  **TraitsATL
看看里面的代码,其实就是定义了一些非CString方法的一些辅助实现方法。                                                                                                           
                                                                                                                   
                                                                                                                
 参考:
    http://blog.kingsamchen.com/archives/550
    http://blog.csdn.net/chenjin824/article/details/1214874                                                                                                        
                                                                                                         

原文地址:https://www.cnblogs.com/tupx/p/3433780.html