c++ - std::u8string与std::string有何不同?

标签 c++ string unicode c++20

如果我有一个字符串:

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和/或以其他方式确保它们已正确编码。但:

  • 其他人的代码可能不同意。因此,您不能使用任何可能返回不使用UTF-8编码的char*的库。
  • 您可能不小心违反了自己的戒律。毕竟,char not_utf8[] = "你好";是有条件支持的C++。该char[]的编码将是编译器的窄编码...无论是什么。在某些编译器上可能是UTF-8,在其他编译器上可能是其他。
  • 您不能告诉其他人的代码(甚至团队中的其他人)您正在做的事情。也就是说,您的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编码,则认为这是用户的错误/行为是不违反契约(Contract)的,这是不合理的。

    我们可以看到缺少类似的基于类型的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。

    关于c++ - std::u8string与std::string有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56420790/

    相关文章:

    python - 弹性查询失败,并显示以下错误异常:TransportError(400,u'search_phase_execution_exception',u'无法解析查询[*/abc *]')

    python - 在 Python 中将 unicode 表情符号转换为 ascii 表情符号

    python-3.x - Python 通过 'Git Bash' 打印 Unicode 字符串得到 'UnicodeEncodeError'

    python - Python 中的另一个 JSON/编码错误

    c++ - 如何使这个 Matrix 类更容易在调试器中使用

    c++ - 解释c中的头文件路径

    C++索引数组打印和删除字符串名称数组打印

    swift - Swift 字符串中区分大小写的字符替换

    c++ - pthread_cond_wait 从 pthread_cond_signal 丢失信号

    c++ - 从 Swift 调用 C++ 函数