c++ 把BSTR导入wstringstream?

bkkx9g8r  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(96)

有一个久经考验的答案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导入?

62lalag4

62lalag41#

就编译器而言,BSTR只是wchar_t*的typedef(它只是在运行时的分配方式与普通的wchar_t C字符串不同)。
根据定义,一个非空的BSTR总是以null结尾的(即使它也是以长度为前缀的)。
所以,除非你的字符串中嵌入了nul字符(这是可能的),否则你可以对宽字符串使用普通的operator<<。只要注意BSTR是空指针的情况,这将对运算符表现出 *undefined行为 *。
试试这个:

std::wstring proc(BSTR bStr)
{
 std::wstringstream ss; 
 ss << L"The string is: ";
 if (bStr) ss << bStr; 
 return ss.str();
}

字符串

bkhjykvo

bkhjykvo2#

[I]s有没有办法避免创建临时ws对象并直接将bStr导入?
是的,当然!
BSTR是一个伪装的wchar_t*,它支持使basic_ostream::operator<<满意的所有要求:它保证是一个nullptr或一个指向CharT值序列的指针,以NUL字符结束。
写作

ss << "The string is: " << bstr;

字符串
是完全有效的。
尽管如此,这样做忽略了两种边缘情况,即BSTR比传统的C风格字符串更宽松:

  • 它可以包含NUL字符作为序列的一部分,从而导致截断
  • 它可以是在输出流中生成实现定义的字符串的nullptr

这两个问题都是不可取的,通过引入std::wstringws作为中介来解决这两个问题。这是我们不能给予的。由于中介是一个不可谈判的需求,问题是:我们能否在不支付(不必要的)分配的代价的情况下获得std::wstring的服务?
从C++17开始,我们就可以了。这个工具叫做std::wstring_view,能够产生“现代”的悬挂指针,同时也解决了手头的问题:

ss << "The string is: " << std::wstring_view(bstr, ::SysStringLen(bStr));


这带回了std::wstring没有价格标签的细节。

1sbrub3j

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”,则此类代码将中断)。

相关问题