提问人:Mr. Boy 提问时间:11/16/2023 最后编辑:Mr. Boy 更新时间:11/18/2023 访问量:116
将 BSTR 管道到 wstringstream 中?
Pipe BSTR into wstringstream?
问:
这里有一个久经考验的答案如何转换 -> .但我想将 BSTR 包含在我正在建立的中。BSTR
std::wstring
wstringstream
显然我可以做到(作为 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
答:
BSTR
就编译器而言,它只是一个 typedef(它只是在运行时的分配方式与普通的 C 字符串不同)。wchar_t*
wchar_t
根据定义,非空总是以 null 结尾(即使它也是以长度为前缀的)。BSTR
因此,除非您的字符串中嵌入了 nul 字符(这是可能的),否则您可以只对宽字符串使用普通字符。只需注意 the 为 null 指针的情况,这将为运算符显示未定义的行为。operator<<
BSTR
试试这个:
std::wstring proc(BSTR bStr)
{
std::wstringstream ss;
ss << L"The string is: ";
if (bStr) ss << bStr;
return ss.str();
}
评论
bStr == nullptr
std::wstring_view(bStr, SysStringLen(bStr))
nullptr
[我]有没有办法避免创建临时对象并直接通过管道进入?
ws
bStr
是的,当然!
BSTR
是一种伪装,它支持使 basic_ostream::operator
满意的所有要求<<:它保证是指向值序列的指针,以字符结尾。wchar_t*
nullptr
CharT
NUL
写作
ss << "The string is: " << bstr;
是完全有效的。
尽管如此,这样做会忽略承认两种边缘情况,其中 a 比传统的 C 样式字符串更宽松:BSTR
- 它可以包含字符作为序列的一部分,从而导致截断
NUL
- 它可以是在输出流中生成实现定义的字符串
nullptr
两者都不可取,这两个问题都可以通过引入作为中间人来解决。这不是我们可以放弃的。由于中介是一个不可协商的要求,问题是:我们能否在不支付(不必要的)分配价格的情况下获得服务?std::wstring
ws
std::wstring
从 C++17 开始,我们可以。该工具称为 std::wstring_view
,能够生成“现代”悬空指针并解决手头的问题:
ss << "The string is: " << std::wstring_view(bstr, ::SysStringLen(bStr));
这带回了没有价格标签的细节。std::wstring
我会将其作为答案发布,即使它应该是评论(针对您自己的帖子和其他回复),并且它实际上并没有解决您的问题(其他人正确地回答),而只是一个(题外话)仅供参考,BSTR 在技术上不是“wchar_t”指针。它实际上是一个 OLECHAR 指针,但由于 OLECHAR 在现代 Windows 上映射到“wchar_t”,因此您可以有效地以这种方式处理它(并且可能在这一点上永远摆脱它,至少在 Windows 上是这样)。
因此,在这一点上(很长一段时间以来),这是一个迂腐的(真正没有实际意义)的问题,但为了在技术上正确(并且老派开发人员经常会这样做),您应该显式地将 BSTR 转换为“wchar_t”指针(甚至是 Windows 上的 TCHAR 指针)然后再将其视为“wchar_t”指针或任何 TCHAR 对于仍在使用它的人来说, 通常也是“wchar_t”)。
How you do this is off-topic here (ancient MFC has ancient macros for it as one possible way - search for "OLE conversion macros" here), but again, in reality you can safely (usually) get away with just treating it as a "wchar_t" pointer on (modern) Windows as you're now doing (since going through the hoops of explicitly converting it to a "wchar_t" pointer on modern Windows will just treat a BSTR as a "wchar_t" pointer anyway - no conversion necessary and the above MFC macros handle things this way).
If you ever need to target an environment where OLECHAR doesn't map to "wchar_t" however, religiously doing the conversion now will correctly handle things in the future (that's what the conversion is for), compared to how you're now handling it (though most do treat a BSTR as a "wchar_t" pointer these days, though in the context that it's still a BSTR so needs to be treated that way, and even Microsoft itself treats it as a "wchar_t" pointer in some of its own sample code and documentation, but it's still an OLECHAR pointer nevertheless so such code will break if you ever target an environment where OLECHAR doesn't map to "wchar_t").
评论
OLECHAR
WCHAR
OLECHAR
CHAR
char*
评论
ss.write(bStr, SysStringLen(bStr))
?ss << "The string is: " << bStr
应该工作,除非它不是以 null 结尾的(这种情况很少见,但在技术上是可行的)。bStr