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

时间:2019-06-03 03:26:44

标签: c++ string unicode c++20

如果我有一个字符串:

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

和C ++ 20中的

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

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

1 个答案:

答案 0 :(得分:7)

由于u8stringstring之间的区别在于,一个是在char8_t上模板化的,另一个是在char上模板化的,所以 real 问题是使用基于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编码的,那么认为这是用户的错误/行为是不违反合同的,这是不合理的。

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

更糟糕的是,如果您尝试将基于UTF-8编码的基于char的字符串传递给path的构造函数……它可以很好地编译。尽管充其量是不可移植的,但它似乎还是可以工作的。

char8_t及其所有类似u8string的附件的存在是为了允许UTF-8用户获得与其他UTF编码相同的功能。在C ++ 20中,filesystem::path将基于char8_t的字符串和u8path will become obsolete.

获得重载。

此外,char8_t并没有特殊的别名语言。因此,采用char8_t为基础的字符串的API 肯定是采用字符数组而不是任意字节数组的API。