c++中的std::string有编码格式吗

xuw*_*ang 3 c++11

我想找到关于 std::string 的默认编码格式。
我试图找出编码格式,但我不知道。c++ 中的 std::string 有编码格式吗?

Ami*_*rsh 7

简单的答案

std::string被定义为std::basic_string<char>这意味着它是一个 chars 的集合。作为字符的集合,它可能包含作为utf8字符串编码结果的字符。

以下代码在 C++20 之前有效:

std::string s = u8"1 ???? Hello";
std::cout << s << std::endl;
Run Code Online (Sandbox Code Playgroud)

而且它打印在支持它的控制台:

1 ?? 你好

u8括号字符串之前是字符串字面量utf8告诉编译器下面的括号内的字符串有utf8编码。

如果没有u8前缀符号,编译器将根据编译器的源编码获取字符串,因此如果默认编码或为编译器显式设置的编码支持字符串中的字符,它也可以像这样:

std::string s = "1 ???? Hello";
std::cout << s << std::endl;
Run Code Online (Sandbox Code Playgroud)

与上面相同的输出。然而,这取决于平台和编译器。

如果编译器的源编码不支持这些字符,例如,如果我们在 gcc 中将源编码设置为带有标志的LATIN-fexec-charset=ISO-8859-1没有u8前缀的字符串会给出以下编译错误

converting to execution character set:
Invalid or incomplete multibyte or wide character 
    std::string s = "1 ???? Hello";
                     ^~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

由于 C++20 u8括号内的字符串不能转换为std::string

std::string s = u8"1 ???? Hello";
std::cout << s << std::endl;
Run Code Online (Sandbox Code Playgroud)

在 C++20 中给出以下编译错误

conversion from 'const char8_t [17]' to non-scalar type 'std::string'
{aka 'std::__cxx11::basic_string<char>'} requested
    std::string s = u8"1 ???? Hello";
                    ^~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

这是因为u8C++20中括号字符串的类型不是const char[SIZE]而是const char8_t[SIZE]char8_tC++20 中引入的类型)。

但是,您可以在 C++20 中使用新类型std::u8string

std::u8string s = u8"1 ???? Hello"; // good - std::u8string added in C++20
// std::cout << s << std::endl; // oops, std::ostream doesn't support u8string
Run Code Online (Sandbox Code Playgroud)

一些有趣的笔记:

  1. 直到 C++20一个带u8括号的字符串是const char[SIZE]
  2. 从 C++20 开始,一个带u8括号的字符串是const char8_t[SIZE]
  3. 大小char8_t是一样的char但它是一个不同类型的

漫长的故事

在 C++ 中编码是一个悲伤的故事。这可能就是您的问题没有“简单答案”的原因。仍然没有一个完全成熟的端到端标准解决方案来处理字符编码。有标准转换器、第 3 方库等。但不是真正紧凑和简单的解决方案。希望 C++23 能解决这个问题。

请参阅关于该主题的 CppCon 2019 会议,作者是 JeanHeyd Meneide

还有一个相关的问题:std::u8string 与 std::string 有何不同?