std::u8string与std::string有何不同?

how std::u8string will be different from std::string?

本文关键字:std 何不同 u8string string      更新时间:2023-10-16

如果我有一个字符串:

std::string s = u8"你好";

而在C++20,

std::u8string s = u8"你好";

std::u8stringstd::string有何不同?

由于u8stringstring之间的区别在于一个在char8_t上模板化,另一个在char上模板化,真正的问题是使用基于char8_t的字符串与使用基于 的字符串有什么区别。 基于char的字符串。

它实际上归结为:基于类型的编码。

任何基于char的字符串(char*char[]string等)都可以用UTF-8编码。但话又说回来,它可能不会。您可以在假设每个等效项char*都将采用 UTF-8 编码的情况下开发代码。您可以在每个字符串文本前面编写一个u8和/或以其他方式确保它们已正确编码。但:

  1. 其他人的代码可能不同意。因此,您不能使用任何可能返回不使用 UTF-8 编码char*的库。

  2. 你可能会不小心违反你自己的戒律。毕竟,char not_utf8[] = "你好";C++是有条件支持的。该char[]的编码将是编译器的窄编码...不管是什么。在某些编译器上可能是 UTF-8,在其他编译器上可能是其他编译器。

  3. 你不能告诉其他人的代码(甚至团队中的其他人)这就是你正在做的事情。也就是说,您的 API 无法声明特定char*是 UTF-8 编码的。这必须是用户在您的文档中假设或以其他方式阅读的内容,而不是他们在代码中看到的内容。

请注意,对于 UTF-16 或 UTF-32 的用户来说,这些问题都不存在。如果使用基于char16_t的字符串,所有这些问题都会消失。如果其他人的代码返回char16_t字符串,您就知道他们在做什么。如果他们返回其他内容,那么您就知道这些内容可能不是 UTF-16。基于 UTF-16 的代码可以与他们的代码互操作。如果编写返回基于char16_t的字符串的 API,则使用代码的每个人都可以从字符串的类型中看到它的编码。这保证是一个编译错误:char16_t not_utf16[] = "你好";

现在,是的,不能保证这些事情中的任何一个。任何特定的char16_t字符串中都可以包含任何值,即使是那些对于 UTF-16 是非法的值。但char16_t表示默认假设为特定编码的类型。鉴于此,如果您提供未使用 UTF-16 编码的此类型的字符串,则认为这是用户的错误/背信弃义并不是没有道理的,这是违反合同的。

我们可以看到C++如何受到 UTF-8 缺乏类似的、基于类型的设施的影响。考虑filesystem::path.它可以采用任何 Unicode 编码的字符串。对于 UTF-16/32,path的构造函数采用基于char16/32_t的字符串。但是你不能将 UTF-8 字符串传递给path的构造函数;基于char的构造函数假定编码是实现定义的窄编码,而不是 UTF-8。所以相反,你必须使用filesystem::u8path,这是一个单独的函数,它返回一个path,由 UTF-8 编码的字符串构造。

更糟糕的是,如果你试图将一个基于 UTF-8 编码char的字符串传递给path的构造函数......它编译得很好。尽管充其量是非便携式的,但它可能看起来可以工作。

char8_t,以及它的所有装备,如u8string,的存在是为了允许UTF-8用户获得与其他UTF编码相同的能力。在 C++20 中,filesystem::path将获得基于char8_t的字符串的重载,并且u8path将变得过时。

而且,作为额外的好处,char8_t周围没有特殊的混叠语言。因此,采用基于char8_t字符串的 API肯定是采用字符数组的 API,而不是任意字节数组。