std::wstring_convert在C++17中被移除,因其自C++11起已被弃用;替代方案为Windows平台使用MultiByteToWideChar,跨平台推荐utf8cpp库,而std::codecvt_utf8_utf16虽存在但已弃用且问题多。

UTF-8转UTF-16时,std::wstring_convert为什么不能用了?
因为C++17起,std::wstring_convert和std::wbuffer_convert已被移除(deprecated in C++11, removed in C++17)。现在直接用它们会编译失败,不是你代码写错,是标准库砍掉了。别查旧教程硬套,得换路子。
主流替代方案就两条:用平台API(Windows用MultiByteToWideChar,Linux/macOS靠iconv或第三方库),或者引入轻量级UTF处理库如utf8cpp。自己手写转换逻辑不现实——边界条件太多,容易漏掉代理对、过长序列、非法字节。
Windows下最稳的转换方式:用MultiByteToWideChar
这是Windows原生API,零依赖、性能好、处理BOM和错误码都可控。关键点不是调两次,而是第一次传nullptr获取长度,第二次填目标缓冲区。
-
CP_UTF8必须作为CodePage参数,别写成CP_ACP或0 - 输入
const char*必须以\0结尾,否则MultiByteToWideChar可能读越界 - 返回值是
wchar_t个数(不含\0),不是字节数;分配std::vector<wchar_t>(len + 1)</wchar_t>再加\0更安全 - 如果输入含非法UTF-8序列,默认会失败(返回0);加
MB_ERR_INVALID_CHARS标志可让其报错,不加则静默替换为U+FFFD
示例片段:
立即学习“C++免费学习笔记(深入)”;
int len = MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, nullptr, 0); if (len == 0) return L""; std::vector<wchar_t> buf(len); MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, buf.data(), len); return std::wstring(buf.data());
跨平台方案:用utf8cpp库一行搞定
头文件只有utf8.h,无编译依赖,适合嵌入式或不想绑死平台的项目。它不处理BOM,也不自动检测编码,纯按UTF-8规则转码。
- 输入必须是合法UTF-8,否则
utf8::utf8to16行为未定义(可能崩溃或截断) - 输出是
std::u16string,不是std::wstring;Windows上sizeof(wchar_t) == 2,二者等价;Linux/macOS上wchar_t是4字节,不能直接赋值 - 若需
std::wstring,且目标平台wchar_t为2字节(如MSVC),可强制转型:std::wstring(reinterpret_cast<const wchar_t>(u16str.data()), u16str.size())</const> - 注意
utf8::utf8to16返回的是std::u16string,别误当成std::string去.c_str()
调用示例:
#include "utf8.h" std::u16string utf16 = utf8::utf8to16(utf8_str);
为什么std::codecvt_utf8_utf16也不推荐?
它还在标准库里,但被标记为deprecated(C++17),且实际使用陷阱多:
- 必须配合
std::wbuffer_convert(已移除)或自定义流缓冲区,代码冗长 - 不同编译器实现差异大:GCC libstdc++里它不支持
std::wstring直接转换,Clang libc++部分版本有bug - 无法控制错误处理策略(比如遇到非法序列是抛异常还是跳过),灵活性差
- 性能比原生API或
utf8cpp低一截,因为绕了IO流抽象层
除非维护非常老的C++11代码且不能升级,否则别碰它。
真正要小心的是:UTF-8字符串是否真的合法、wchar_t在目标平台是否真代表UTF-16、以及BOM要不要保留——这三个点没理清,转出来的东西看着像,用起来就崩。


















