有一个久经考验的答案here如何转换BSTR
-> std::wstring
。但我想在我建立的wstringstream
中包括BSTR。
显然我可以做(有点做作的MRE):
std::wstring proc(BSTR bStr)
{
std::wstringstream ss;
std::wstring ws(bStr, SysStringLen(bStr));
ss << "The string is: " << ws;
return ss.str();
}
字符串
但是,有没有一种方法可以避免创建临时ws
对象并直接将bStr
导入?
3条答案
按热度按时间62lalag41#
就编译器而言,
BSTR
只是wchar_t*
的typedef(它只是在运行时的分配方式与普通的wchar_t
C字符串不同)。根据定义,一个非空的
BSTR
总是以null结尾的(即使它也是以长度为前缀的)。所以,除非你的字符串中嵌入了nul字符(这是可能的),否则你可以对宽字符串使用普通的
operator<<
。只要注意BSTR
是空指针的情况,这将对运算符表现出 *undefined行为 *。试试这个:
字符串
bkhjykvo2#
[I]s有没有办法避免创建临时
ws
对象并直接将bStr
导入?是的,当然!
BSTR
是一个伪装的wchar_t*
,它支持使basic_ostream::operator<<
满意的所有要求:它保证是一个nullptr
或一个指向CharT
值序列的指针,以NUL
字符结束。写作
字符串
是完全有效的。
尽管如此,这样做忽略了两种边缘情况,即
BSTR
比传统的C风格字符串更宽松:NUL
字符作为序列的一部分,从而导致截断nullptr
这两个问题都是不可取的,通过引入
std::wstring
ws
作为中介来解决这两个问题。这是我们不能给予的。由于中介是一个不可谈判的需求,问题是:我们能否在不支付(不必要的)分配的代价的情况下获得std::wstring
的服务?从C++17开始,我们就可以了。这个工具叫做
std::wstring_view
,能够产生“现代”的悬挂指针,同时也解决了手头的问题:型
这带回了
std::wstring
没有价格标签的细节。1sbrub3j3#
我会把这个作为一个答案,即使它应该是一个评论。(对你自己的帖子和其他回复),它实际上并没有解决你的问题(其他人正确地有),但只是一个(题外话)仅供参考,BSTR在技术上不是“wchar_t”指针,它实际上是一个OLECHAR指针,但由于OLECHAR在现代Windows上Map到“wchar_t”,因此您可以有效地以这种方式处理它(在这一点上,至少在Windows上,可能永远不会受到惩罚)。
因此,这是一个迂腐的(实际上是一个无意义的问题)(很长一段时间了),但技术上是正确的(这方面的老派开发人员通常会这样做),您应该显式地将BSTR转换为“wchar_t”指针(或者甚至是Windows上的TCHAR指针),然后再这样处理它。(作为“wchar_t”指针或任何TCHAR,对于那些仍然使用它的人来说,通常也是“wchar_t”)。
你是怎么做到的已经离题了(古代MFC有古代宏作为一种可能的方法-搜索“*OLE转换宏 *”here),但同样,在现实中,你可以安全地(通常)摆脱只是把它作为一个“wchar_t”指针在(现代)Windows上,因为你现在这样做(因为在现代Windows上,通过显式地将其转换为“wchar_t”指针的方法,无论如何都会将BSTR视为“wchar_t”指针-不需要转换,并且上面的MFC宏以这种方式处理)。
但是,如果您需要将OLECHAR不Map到“wchar_t”的环境作为目标,那么现在认真地进行转换将在将来正确地处理事情(这就是转换的目的),与您现在处理它的方式相比,(尽管现在大多数人都把BSTR当作“wchar_t”指针,尽管在上下文中它仍然是一个BSTR,所以需要这样对待,甚至微软自己也在它自己的一些示例代码和文档中将其视为“wchar_t”指针,但它仍然是一个OLECHAR指针,因此如果您的目标环境中OLECHAR不Map到“wchar_t”,则此类代码将中断)。