std::wstring vs std::string:如何为Unicode选择?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程
```html

引言:两个字符串,一个难题

\n\n

每个C++开发者迟早都会面临一个困境:std::string还是std::wstring?它们看起来都是字符串,都来自STL,但行为却截然不同。在处理多语言文本、表情符号或象形文字时,这个问题尤为突出。

\n\n

如果你正在用C++编写程序,并且希望它能够正确处理俄语、日语或阿拉伯语的"Hello, world!"——那么理解std::string和std::wstring之间的区别就必不可少。在本文中,我们将深入分析这两种方法,按关键参数进行比较,并决定何时使用哪一种。

\n\n
本文内容基于Stack Overflow上一个浏览量达数千的真实问题。我们对其进行了改写,添加了示例和清晰的结构,使其更适合用于教学。
\n\n

std::string:经典且简洁

\n\n

std::string是std::basic_string<char>的别名。每个字符占用1个字节。历史上,char用于ASCII字符,但如今它通常存储UTF-8编码(或仅仅是字节)的数据。

\n\n

std::string 的优点

\n
    \n
  • 内存效率高 —— 对于ASCII/UTF-8,每个字符只需1字节。
  • \n
  • 兼容性好 —— 可与大多数库(包括C函数如strlen、strcpy)协同工作。
  • \n
  • 速度快 —— 内存分配的开销较小。
  • \n
  • 应用广泛 —— 是网络传输和JSON数据交换的事实标准。
  • \n
\n\n

std::string 的缺点

\n
    \n
  • 编码混淆 —— std::string不知道数据存储的编码。它可以存储UTF-8,但.size()返回的是字节数而非字符数。
  • \n
  • Unicode问题 —— 遍历字符串时可能会破坏多字节字符。
  • \n
  • 缺乏对宽字符的内置支持 —— 要处理UTF-8之外的Unicode,需要使用第三方库。
  • \n
\n\n
// 示例:使用UTF-8的std::string\n#include <iostream>\n#include <string>\n\nint main() {\n    std::string s = "Привет, мир!";\n    std::cout << "字节长度: " << s.size() << std::endl; // 21个字节\n    std::cout << "第一个字符(作为char): " << s[0] << std::endl; // 乱码:UTF-8的第一个字节\n    return 0;\n}
\n\n

在这个例子中,s[0]返回的不是'П',而是两字节字符'П'(0xD0)的第一个字节。这是初学者常犯的错误。

\n\n

std::wstring:宽字符的力量

\n\n

std::wstring是std::basic_string<wchar_t>。wchar_t的大小取决于平台:在Windows上是2字节(UTF-16),在Linux/macOS上是4字节(UTF-32)。

\n\n

std::wstring 的优点

\n
    \n
  • 固定字符大小(在特定平台上)—— 简化了Unicode操作。
  • \n
  • 本地化支持直接 —— 在Windows上,所有WinAPI函数都使用wchar_t。
  • \n
  • 多字节字符问题少 —— 每个字符都是字符串的一个元素。
  • \n
\n\n

std::wstring 的缺点

\n
    \n
  • 大小依赖于平台 —— 代码在Windows和Linux上可能行为不同。
  • \n
  • 内存消耗更高 —— 每个字符占用2或4字节,即使对于ASCII字符也是如此。
  • \n
  • 兼容性问题 —— 并非所有库都支持wchar_t。
  • \n
  • 代理对问题 —— 在UTF-16中,某些字符(如表情符号)占用2个wchar_t单元,这再次导致了"字符≠元素"的问题。
  • \n
\n\n
// 示例:Windows上的std::wstring\n#include <iostream>\n#include
```                

博客

书籍推荐