CComBSTR(二)
从前边的叙述中可以看出BSTR的含义很丰富,限制也比较多。这样我们在使用过程中就得很小心。实际编程过程中,BSTR的应用又很频繁。为了避免一些不必要的麻烦,ATL提供了一个类把他包装起来,使得我们不必过多的关心他的细节。
CComBSTR把一个BSTR作为成员变量,通过各种方法对他进行维护。
以下是该类的具体内容及其注意事项:
构造函数和析构函数
Ø CComBSTR(); m_str = NULL;
BSTR为NULL的时候,有时候同于一个指向控字符串””的指针。如VB中IF “”=P的返回值会为真。但是,很多BSTR相关的WIN32 API不一定会有此认同,他们要求被操作的BSTR必须不为空。如SysStringLen
Ø CComBSTR(LPOLESTR pSrc);
不停的复制字符直到NUL终止符。
Ø CComBSTR(int size, LPOLESTR pSrc);
首先创建一个size大小的BSTR,然后copy pSrc中复制包括NUL在内的任何字符,然后加一个NUL作后缀。如果pSrc为空,则构造一个大小为size的没有初始化的BSTR。
Ø CComBSTR(int size);
则构造一个大小为size的没有初始化的BSTR
Ø CComBSTR(const CComBSTR src)
调用了对象的Copy方法。
由于Copy是更具自己的长度构造的一个拷贝,所以能够正确复制(包括内嵌NUL字符)
Ø #ifndef OLE2ANSI
CComBSTR(LPCSTR pSrc);
CComBSTR(int size, LPCSTR pSrc);
#endif
这两个函数同上边的两个函数基本一致,不同的是,他们不能有内嵌NUL。而且当定义了OLE2ANSI的时候LPCSTR = LPOLESTR,下边的函数就不能再有了。
Ø CComBSTR(REFGUID src)
生成一个包含GUID的字符串。
析构函数~ CComBSTR() {::SysFreeString(m_str)}
应为他会自动释放BSTR,所以在处理异常处理的时候非常有用。
注意,内嵌NUL的字符串。不是说只有按照BSTR的含义去理解LPOLESTR才能得到内嵌NUL的字符串。因为LPOLESTR实际上是一个OLECHAR的数组,他的长度有数组的性质来决定,所以在NUL后边还可以有其他内容。只是我们把它仅仅理解城LPOLESTR的时候,他的有效长度仅仅是第一个NUL之前的长度。所以会出现CComBSTR(int size, LPOLESTR pSrc)来构造内嵌NUL的字符串。但是这样的数组绝对不是BSTR,因为BSTR的首字节记录了该串的长度。
初始化
CComBSTR& operator=(const CComBSTR& src)
CComBSTR& operator=(LPCOLESTR pSrc)
#ifndef OLE2ANSI
CComBSTR& operator=(LPCSTR pSrc)
#endif
bool LoadString(HINSTANCE hInst, UINT nID)
bool LoadString(UINT nID)
这三个初始化函数都是先把m_str原来所指的BSTR释放,然后根据参数进行初始化。第一个初始化函数能够准确的(包含NUL字符)制造一个副本。而后边两个只能按照以NUL结尾的字符串进行初始化。第四个是根据hInst资源句柄去加载字符串,而最后一个其实也一样,只不过资源句柄是一个全局变量_pModule->m_hInstResource,_pModule在服务器对象初始化的时候确定(在DllMain或WinMain中调用CComModule::Init)。
操作符
Ø operator BSTR() const
当显式地或者隐式地把一个CComBSTR对象强制转换成一个BSTR对象的时候就会调用这个方法
Ø BSTR* operator&()
注意这个方法返回的是内部变量的地址,如果我们在改变这个变量之前没有释放原来的字符串会导致内存泄漏。但是,用它来接收一个BSTR的时候很有用,我们这样可以直接用CComBSTR来管理BSTR的生命周期。
HRESULT get_Name(/*out*/BSTR* pName);
CComBSTR bstrName;
Get_Name(bstrName);
Ø HRESULT CopyTo(BSTR* pbstr)
精确地构造一个副本,用它来给调用这构造返回值比较合适。注意,我们需要显式地式方pbstr。
Ø BSTR Detach()
他返回了m_str,而且把自己清空,如果利用Copy的话就会构造一个副本,效率比较低。CComBSTR析构的时候不会做任何事情。但是,我们需要显式地式方它的返回值。
Ø void Attach(BSTR src)
接收一个BSTR用CComBSTR来维护他的生命周期。如果把一个BSTR附加在一个非空的CComBSTR上,就会产生内存泄漏。
Ø void Empty()
释放内存并且清空CComBSTR。
Ø 一个非空CComBSTR调用Attach之前一般调用Empty()。
连接字符
HRESULT Append() 4个
HRESULT AppendBSTR(BSTR p)
CComBSTR& operator+=(const CComBSTR& bstrSrc)
当参数是BSTR或者CComBSTR的时候会附加整个BSTR,但如果是LPCOLECHAR或LPCSTR会添以NUL结尾的字符串。
字符大小写转换
ToLower ToUpper。实现的时候总是OLE2T->XXX->T2OLE。所以一般是由损失的,因为专成TCHAR字符串的时候会议NUL终止。内嵌NUL的字符串会出问题。
比较操作
bool operator!() const
bool operator<(BSTR bstrSrc) const
bool operator<(LPCSTR pszSrc) const
bool operator==(BSTR bstrSrc) const
bool operator==(LPCSTR pszSrc) const
在比较参数为BSTR的时候,内部会用wcscmp来比较,所以在字符串转换的时候会因为NUL造成损失。
对永久性的支持。
HRESULT WriteToStream(IStream* pStream)
他把表示BSTR长度(字节为单位SysStringByteLen)的ULONG计数值写入流中。紧接着写入BSTR。
HRESULT ReadFromStream(IStream* pStream)
他是上一过程的相反,但是如果一个非空的CComBSTR调用该函数是事先不会清空,会产生内存泄漏。
心得:
首先就是OLECHAR*和BSTR的区别和联系。编译器认定他们是相同的,但是他们确确实实不同。使用的时候应该非常注意才对。
另外就是涉及到内嵌NUL的字符串的处理。CComBSTR做的并不完美。
还有就是内存问题。自己时刻注意什么时候应该释放内存。
转自:http://zhikangs.spaces.live.com/blog/
从前边的叙述中可以看出BSTR的含义很丰富,限制也比较多。这样我们在使用过程中就得很小心。实际编程过程中,BSTR的应用又很频繁。为了避免一些不必要的麻烦,ATL提供了一个类把他包装起来,使得我们不必过多的关心他的细节。
CComBSTR把一个BSTR作为成员变量,通过各种方法对他进行维护。
以下是该类的具体内容及其注意事项:
构造函数和析构函数
Ø CComBSTR(); m_str = NULL;
BSTR为NULL的时候,有时候同于一个指向控字符串””的指针。如VB中IF “”=P的返回值会为真。但是,很多BSTR相关的WIN32 API不一定会有此认同,他们要求被操作的BSTR必须不为空。如SysStringLen
Ø CComBSTR(LPOLESTR pSrc);
不停的复制字符直到NUL终止符。
Ø CComBSTR(int size, LPOLESTR pSrc);
首先创建一个size大小的BSTR,然后copy pSrc中复制包括NUL在内的任何字符,然后加一个NUL作后缀。如果pSrc为空,则构造一个大小为size的没有初始化的BSTR。
Ø CComBSTR(int size);
则构造一个大小为size的没有初始化的BSTR
Ø CComBSTR(const CComBSTR src)
调用了对象的Copy方法。
由于Copy是更具自己的长度构造的一个拷贝,所以能够正确复制(包括内嵌NUL字符)
Ø #ifndef OLE2ANSI
CComBSTR(LPCSTR pSrc);
CComBSTR(int size, LPCSTR pSrc);
#endif
这两个函数同上边的两个函数基本一致,不同的是,他们不能有内嵌NUL。而且当定义了OLE2ANSI的时候LPCSTR = LPOLESTR,下边的函数就不能再有了。
Ø CComBSTR(REFGUID src)
生成一个包含GUID的字符串。
析构函数~ CComBSTR() {::SysFreeString(m_str)}
应为他会自动释放BSTR,所以在处理异常处理的时候非常有用。
注意,内嵌NUL的字符串。不是说只有按照BSTR的含义去理解LPOLESTR才能得到内嵌NUL的字符串。因为LPOLESTR实际上是一个OLECHAR的数组,他的长度有数组的性质来决定,所以在NUL后边还可以有其他内容。只是我们把它仅仅理解城LPOLESTR的时候,他的有效长度仅仅是第一个NUL之前的长度。所以会出现CComBSTR(int size, LPOLESTR pSrc)来构造内嵌NUL的字符串。但是这样的数组绝对不是BSTR,因为BSTR的首字节记录了该串的长度。
初始化
CComBSTR& operator=(const CComBSTR& src)
CComBSTR& operator=(LPCOLESTR pSrc)
#ifndef OLE2ANSI
CComBSTR& operator=(LPCSTR pSrc)
#endif
bool LoadString(HINSTANCE hInst, UINT nID)
bool LoadString(UINT nID)
这三个初始化函数都是先把m_str原来所指的BSTR释放,然后根据参数进行初始化。第一个初始化函数能够准确的(包含NUL字符)制造一个副本。而后边两个只能按照以NUL结尾的字符串进行初始化。第四个是根据hInst资源句柄去加载字符串,而最后一个其实也一样,只不过资源句柄是一个全局变量_pModule->m_hInstResource,_pModule在服务器对象初始化的时候确定(在DllMain或WinMain中调用CComModule::Init)。
操作符
Ø operator BSTR() const
当显式地或者隐式地把一个CComBSTR对象强制转换成一个BSTR对象的时候就会调用这个方法
Ø BSTR* operator&()
注意这个方法返回的是内部变量的地址,如果我们在改变这个变量之前没有释放原来的字符串会导致内存泄漏。但是,用它来接收一个BSTR的时候很有用,我们这样可以直接用CComBSTR来管理BSTR的生命周期。
HRESULT get_Name(/*out*/BSTR* pName);
CComBSTR bstrName;
Get_Name(bstrName);
Ø HRESULT CopyTo(BSTR* pbstr)
精确地构造一个副本,用它来给调用这构造返回值比较合适。注意,我们需要显式地式方pbstr。
Ø BSTR Detach()
他返回了m_str,而且把自己清空,如果利用Copy的话就会构造一个副本,效率比较低。CComBSTR析构的时候不会做任何事情。但是,我们需要显式地式方它的返回值。
Ø void Attach(BSTR src)
接收一个BSTR用CComBSTR来维护他的生命周期。如果把一个BSTR附加在一个非空的CComBSTR上,就会产生内存泄漏。
Ø void Empty()
释放内存并且清空CComBSTR。
Ø 一个非空CComBSTR调用Attach之前一般调用Empty()。
连接字符
HRESULT Append() 4个
HRESULT AppendBSTR(BSTR p)
CComBSTR& operator+=(const CComBSTR& bstrSrc)
当参数是BSTR或者CComBSTR的时候会附加整个BSTR,但如果是LPCOLECHAR或LPCSTR会添以NUL结尾的字符串。
字符大小写转换
ToLower ToUpper。实现的时候总是OLE2T->XXX->T2OLE。所以一般是由损失的,因为专成TCHAR字符串的时候会议NUL终止。内嵌NUL的字符串会出问题。
比较操作
bool operator!() const
bool operator<(BSTR bstrSrc) const
bool operator<(LPCSTR pszSrc) const
bool operator==(BSTR bstrSrc) const
bool operator==(LPCSTR pszSrc) const
在比较参数为BSTR的时候,内部会用wcscmp来比较,所以在字符串转换的时候会因为NUL造成损失。
对永久性的支持。
HRESULT WriteToStream(IStream* pStream)
他把表示BSTR长度(字节为单位SysStringByteLen)的ULONG计数值写入流中。紧接着写入BSTR。
HRESULT ReadFromStream(IStream* pStream)
他是上一过程的相反,但是如果一个非空的CComBSTR调用该函数是事先不会清空,会产生内存泄漏。
心得:
首先就是OLECHAR*和BSTR的区别和联系。编译器认定他们是相同的,但是他们确确实实不同。使用的时候应该非常注意才对。
另外就是涉及到内嵌NUL的字符串的处理。CComBSTR做的并不完美。
还有就是内存问题。自己时刻注意什么时候应该释放内存。
转自:http://zhikangs.spaces.live.com/blog/