BSTR类型跟_bstr_t区别
BSTR BSXML=m_pSetting-> Load(CCQRMainApp::GetDataSecurityObj(),bstrUser,bstrName);
在XP下有时候出错
而用
_bstr_t BSXML=m_pSetting-> Load(CCQRMainApp::GetDataSecurityObj(),bstrUser,bstrName);
就不会出错
让我们看看BSTR的声明
typedef /* [wire_marshal] */ OLECHAR *BSTR;
typedef WCHAR OLECHAR;
这说明BSTR仅仅是一个OLECHAR *(WCHAR *)指针,那么取得返回值的时候,这个指针指向的实际上是由COM已经封装成_bstr_t的对象的地址,这个对象什么时候应该被释放呢,COM里对一个对象的引用计数为0的时候,会自动被释放。但是这里只是一个指向这个对象的指针,并没有增加引用计数,所以系统就认为该释放了。指针指向一个有可能已经被释放的地址,是不恰当的
_bstr_t BSXML=重载了这个操作符,我们看看他的实现
// Default assign operator
//
inline _bstr_t& _bstr_t::operator=(const _bstr_t& s) throw()
{
if (this != &s) {
_Free();
m_Data = s.m_Data;
_AddRef();
}
return *this;
}
由于_bstr_t对象会增加引用计数,那么load方法返回的_bstr_t对象的引用计数不是0,那么在之后的引用改变量的时候,就不会被认为该释放了
虽然2000下XP下表现不同,我也说不清楚。但不能认为第一种方式就应该被认为是恰当的,还是以第二种方法更为保险。
另外,为什么load方法参数里是BSTR ,按理说应该是一个单纯的指针。当一个BSTR作为返回值的时候,要跨越该方法的作用域,那么只能把这个指针封装成一个_bstr_t对象来放回,而不是一个单纯的BSTR,因为引用计数可以保证在恰当的时候,释放为了返回字符串而分配的内存。如果调用该方法的时候,没有增加引用计数,很难保证返回的bstr何时被释放掉
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++7.关于CString和其他一些自动化类型的相互转换问题.
未参考的资源: 在各种字符串类型之间进行转换
http://msdn2.microsoft.com/zh-cn/library/ms235631.aspx
类型类别:CString ,VARIANT,BSTR,_t_btr,等
预备知识:
BSTR:根据MSDN,他的内部结构为:4字节的长度前缀(字节单位),字符串(宽),2字节结束标志0x0000.平常的BSTR是指向字符串的第一字节,并非前缀.比如定义BSTR myBstr=L” I am a happy BSTR”,这样其实不正确,并没有正确生成前缀.应该这样: BSTR MyBstr = SysAllocString(L"I am a happy BSTR");这样就会在内存分配时就会加上前缀和结束标志.
_bstr_t: _bstr_t是C++对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTR API函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib
CComBSTR: CComBSTR是对BSTR数据类型封装的一个ATL类.
CComBSTR bstr1;
bstr1 = "Bye"; // 直接赋值
OLECHAR* str = OLESTR("ta ta"); // 长度为5的宽字符
CComBSTR bstr2(wcslen(str)); // 定义长度为5
wcscpy(bstr2.m_str, str); // 将宽字符串复制到BSTR中
CComBSTR bstr3(5, OLESTR("Hello World"));
CComBSTR bstr4(5, "Hello World");
CComBSTR bstr5(OLESTR("Hey there"));
CComBSTR bstr6("Hey there");
CComBSTR bstr7(bstr6);
VARIANT,_variant_t
_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
参考如下代码:
_variant_t:
long l=222; ing i=100; _variant_t lVal(l); lVal = (long)i;
COleVariant:
COleVariant v3 = "字符串", v4 = (long)1999; CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;
// 构造时复制,内容为"Hey there"
(1).BSTR和CString的相互转换
BSTR->CString :BSTR可直接赋值给CString.cstring=myBstr
CString->BSTR: myBstr=cstring.AllocSysString();
(2)char * 和BSTR
Char * ->BSTR:
char * pChar="Hello!";
BSTR myBstr=_com_util::ConvertStringToBSTR(pChar);
::SysFreeString(myBstr);//这个函数作用后myBstr仍存在,还可赋值给cstring,令人费解.
BSTR->char *:
char *p=_com_util::ConvertBSTRToString(myBstr);
delete p;//指针delete后还可访问,只是只想的是乱码.
(3)char *和_bstr_t,
Char * ->_bstr_t: 1.直接赋值:如_bstr_t bstr;char * pChar=”hello!”;2.pChar作为_bstr_t的构造参数:char * pChar=”Hello!”;_bstr_t bstr(pChar);
_bstr_t-> char *:_bstr_t bstr ;char *pChar=(LPTSTR)bstr
(4)_bst_t和BSTR
_bstr_t->BSTR:BSTR操作符.
BSTR->_bstr_t:_bstr_t的构造函数.
(5) CComBSTR:
内部有BSTR类型的公有成员m_str.
To char:
LPCTSTR操作符
To BSTR:
BSTR操作符
To _bstr_t:
先使用BSTR操作符或直接取其m_str成员, 作为_bstr_t的构造函数
由于CComBSTR中的数据成员BSTR m_str公开, 而且重载了&操作符, 适合作为以BSTR作 为传出参数的函数, 但要注意内存泄漏问题, 不要将已赋值的CComBSTR作为传出参数
(6) VARIANT, CString , _variant_t,这个只举几个小例子:
CString 放到VARIANT 中:
CString temp=”Aloha”;
variant.vt=VT_BSTR;
variant.bstrVal=temp.AllocSysString();//似乎这里的CString包含的是宽字符.
VARIANT 到CString
CString=(LPCTSTR)(_bstr_t)_variant_t
(7)CString,Int Char *,float
----------------------------------------------------------------------------------------------------------------------
Char * Int: atoi();这里涉及到一些细节:转换在碰到非法字符时停下,并保留已经转换的值 ,比如”1asd”转换后返回1,”asd”返回0,也就是没有转换。
CString->Int:
Int- >CString: int n=atoi(str.GetBuffer(0));
函数原型: int atoi(
const char *str
); 返回值为转换结果。,若无法转换,则返回0.
CString temp;
Temp.Format(“%d”,nTemp);
IntChar *:
转换函数原型: char *_itoa(
int value,
char *string,
int radix
);
radix :Base of value; must be in the range 2 – 36. 进制数.十进制就是10.
----------------------------------------------------------------------------------------------------------------------
CString Float :
float f=atof(str.GetBuffer(0));
FloatCString:
str.Format("%f",f);
在XP下有时候出错
而用
_bstr_t BSXML=m_pSetting-> Load(CCQRMainApp::GetDataSecurityObj(),bstrUser,bstrName);
就不会出错
让我们看看BSTR的声明
typedef /* [wire_marshal] */ OLECHAR *BSTR;
typedef WCHAR OLECHAR;
这说明BSTR仅仅是一个OLECHAR *(WCHAR *)指针,那么取得返回值的时候,这个指针指向的实际上是由COM已经封装成_bstr_t的对象的地址,这个对象什么时候应该被释放呢,COM里对一个对象的引用计数为0的时候,会自动被释放。但是这里只是一个指向这个对象的指针,并没有增加引用计数,所以系统就认为该释放了。指针指向一个有可能已经被释放的地址,是不恰当的
_bstr_t BSXML=重载了这个操作符,我们看看他的实现
// Default assign operator
//
inline _bstr_t& _bstr_t::operator=(const _bstr_t& s) throw()
{
if (this != &s) {
_Free();
m_Data = s.m_Data;
_AddRef();
}
return *this;
}
由于_bstr_t对象会增加引用计数,那么load方法返回的_bstr_t对象的引用计数不是0,那么在之后的引用改变量的时候,就不会被认为该释放了
虽然2000下XP下表现不同,我也说不清楚。但不能认为第一种方式就应该被认为是恰当的,还是以第二种方法更为保险。
另外,为什么load方法参数里是BSTR ,按理说应该是一个单纯的指针。当一个BSTR作为返回值的时候,要跨越该方法的作用域,那么只能把这个指针封装成一个_bstr_t对象来放回,而不是一个单纯的BSTR,因为引用计数可以保证在恰当的时候,释放为了返回字符串而分配的内存。如果调用该方法的时候,没有增加引用计数,很难保证返回的bstr何时被释放掉
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++7.关于CString和其他一些自动化类型的相互转换问题.
未参考的资源: 在各种字符串类型之间进行转换
http://msdn2.microsoft.com/zh-cn/library/ms235631.aspx
类型类别:CString ,VARIANT,BSTR,_t_btr,等
预备知识:
BSTR:根据MSDN,他的内部结构为:4字节的长度前缀(字节单位),字符串(宽),2字节结束标志0x0000.平常的BSTR是指向字符串的第一字节,并非前缀.比如定义BSTR myBstr=L” I am a happy BSTR”,这样其实不正确,并没有正确生成前缀.应该这样: BSTR MyBstr = SysAllocString(L"I am a happy BSTR");这样就会在内存分配时就会加上前缀和结束标志.
_bstr_t: _bstr_t是C++对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTR API函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib
CComBSTR: CComBSTR是对BSTR数据类型封装的一个ATL类.
CComBSTR bstr1;
bstr1 = "Bye"; // 直接赋值
OLECHAR* str = OLESTR("ta ta"); // 长度为5的宽字符
CComBSTR bstr2(wcslen(str)); // 定义长度为5
wcscpy(bstr2.m_str, str); // 将宽字符串复制到BSTR中
CComBSTR bstr3(5, OLESTR("Hello World"));
CComBSTR bstr4(5, "Hello World");
CComBSTR bstr5(OLESTR("Hey there"));
CComBSTR bstr6("Hey there");
CComBSTR bstr7(bstr6);
VARIANT,_variant_t
_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
参考如下代码:
_variant_t:
long l=222; ing i=100; _variant_t lVal(l); lVal = (long)i;
COleVariant:
COleVariant v3 = "字符串", v4 = (long)1999; CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;
// 构造时复制,内容为"Hey there"
(1).BSTR和CString的相互转换
BSTR->CString :BSTR可直接赋值给CString.cstring=myBstr
CString->BSTR: myBstr=cstring.AllocSysString();
(2)char * 和BSTR
Char * ->BSTR:
char * pChar="Hello!";
BSTR myBstr=_com_util::ConvertStringToBSTR(pChar);
::SysFreeString(myBstr);//这个函数作用后myBstr仍存在,还可赋值给cstring,令人费解.
BSTR->char *:
char *p=_com_util::ConvertBSTRToString(myBstr);
delete p;//指针delete后还可访问,只是只想的是乱码.
(3)char *和_bstr_t,
Char * ->_bstr_t: 1.直接赋值:如_bstr_t bstr;char * pChar=”hello!”;2.pChar作为_bstr_t的构造参数:char * pChar=”Hello!”;_bstr_t bstr(pChar);
_bstr_t-> char *:_bstr_t bstr ;char *pChar=(LPTSTR)bstr
(4)_bst_t和BSTR
_bstr_t->BSTR:BSTR操作符.
BSTR->_bstr_t:_bstr_t的构造函数.
(5) CComBSTR:
内部有BSTR类型的公有成员m_str.
To char:
LPCTSTR操作符
To BSTR:
BSTR操作符
To _bstr_t:
先使用BSTR操作符或直接取其m_str成员, 作为_bstr_t的构造函数
由于CComBSTR中的数据成员BSTR m_str公开, 而且重载了&操作符, 适合作为以BSTR作 为传出参数的函数, 但要注意内存泄漏问题, 不要将已赋值的CComBSTR作为传出参数
(6) VARIANT, CString , _variant_t,这个只举几个小例子:
CString 放到VARIANT 中:
CString temp=”Aloha”;
variant.vt=VT_BSTR;
variant.bstrVal=temp.AllocSysString();//似乎这里的CString包含的是宽字符.
VARIANT 到CString
CString=(LPCTSTR)(_bstr_t)_variant_t
(7)CString,Int Char *,float
----------------------------------------------------------------------------------------------------------------------
Char * Int: atoi();这里涉及到一些细节:转换在碰到非法字符时停下,并保留已经转换的值 ,比如”1asd”转换后返回1,”asd”返回0,也就是没有转换。
CString->Int:
Int- >CString: int n=atoi(str.GetBuffer(0));
函数原型: int atoi(
const char *str
); 返回值为转换结果。,若无法转换,则返回0.
CString temp;
Temp.Format(“%d”,nTemp);
IntChar *:
转换函数原型: char *_itoa(
int value,
char *string,
int radix
);
radix :Base of value; must be in the range 2 – 36. 进制数.十进制就是10.
----------------------------------------------------------------------------------------------------------------------
CString Float :
float f=atof(str.GetBuffer(0));
FloatCString:
str.Format("%f",f);
还没人赞这篇日记