使用字符串构造函数从wstring转换为字符串时,是否没有可能的数据丢失

Is there no possible loss of data when converting from wstring to string using string constructor?

本文关键字:字符串 有可能 是否 数据 构造函数 wstring 转换      更新时间:2023-10-16

当我执行以下操作时,编译器会警告我可能会丢失数据(但编译成功):

std::vector<wchar_t> v1;
v1.push_back(L'a');
std::vector<char> v2(v1.begin(), v1.end());

当我做以下事情时,我没有收到这样的警告,而且据我所知,我过去做过的时候没有丢失数据:

std::wstring w1;
w1 = L"a";
std::string s1(w1.begin(), w1.end());

事实上,第二个片段中是否没有可能的数据丢失?如果,为什么不呢?basic_string构造函数中是否有处理其他类型字符迭代器可能性的东西?或者迭代器本身有什么特别之处?

为了给出一个具体的例子,如果您编写

std::wstring w1 = L"τ"; // That's a Unicode Greek Small Letter Tau (U+03C4)
std::string  s1(w1.begin(), w1.end());

最有可能的是,您最终会得到一个包含字符0xC4的字符串,该字符在Windows ANSI和ISO Latin-1中都是"。这可能不是您想要的,虽然如果您坚持ASCII,它在大多数平台上都可以正常工作,但即使这样也不能保证(例如,如果您的代码在IBM大型机上运行,您可能会发现窄字符串是EBCDIC,宽字符串可能有任何数量的不寻常编码)。

如果要将宽字符串转换为窄字符串,则需要使用适当的函数来处理涉及字符编码的事实。C++并没有真正提供一种体面的方法来实现这一点;通常,您必须恢复到C的wctombs()函数,或者使用特定于平台的API。(有人可能会指出narrowctype方面,但这只是意味着任何不能用单个字节表示的字符都会被指定的字符替换;这并不是真正的转换。此外,C++11支持使用wstring_convert在Unicode字符串之间进行转换,但这只适用于Unicode,并不是每个人都将其用于窄字符和宽字符。)。)

是的,第二个片段将以与第一个片段相同的方式丢失数据(截断字符值)。您的库实现可能正在执行抑制警告消息的操作。如果不查看特定库实现的源代码,就不可能知道。