zoukankan      html  css  js  c++  java
  • 浅析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                                                                                                        
                                                                                                             

  • 相关阅读:
    [de2_tv] PAL制TV_VGA
    【转】NiosII中SDRAM相移计算
    VGA controller的代码分析
    TIOBE 2012年2月编程语言排行榜:C#力压C++
    ZendFramework入门2 使用布局
    转载 20个数据库设计最佳实践
    转载 20个很有用的CSS图形和图表技术和教程
    转载 10款实用的Ajax/JavaScript编码工具推荐
    转载 打造优秀Web设计的10项原则
    2012年1月编程语言排行榜:ObjectiveC成为年度语言
  • 原文地址:https://www.cnblogs.com/tupx/p/3433780.html
Copyright © 2011-2022 走看看