首页 > 解决方案 > 在 std::string 中使用非法 UTF-8 八位字节作为分隔符

问题描述

希望我的问题得到改进和更集中的版本:

由于解释起来会产生误导(见下文),我必须在一个字符串中存储几个 UTF-8 编码的字符串。(这里的字符串表示 C++ std::string

我的方法是将字符串与非法 UTF-8 八位字节(0xC0、0xC1、0xF5-0xFF)之一作为分隔符,因为这些八位字节永远不会出现在有效的 UTF-8 序列中。(由于 0x00 是一个有效的 UTF-8 八位字节,我认为它不适合我的预期误用。)

除了关于性能的所有考虑因素之外,我不知道这种方法有什么问题吗?是否有任何理由偏爱其中一个非法八位位组?

..

在我最初的问题中,我试图提供更多的背景信息,但这导致了一些关于性能问题和预期权衡的问题。但我的问题不在于这些权衡,而在于我的方法在技术上的可行性和有效性。

标签: c++utf-8c++14

解决方案


正如其他人所提到的,使用适用于您的情况的任何字节都可以在std::string. 尽管如果您的字符串不以其他方式使用'\0',则使用此类而不是非法的 UTF-8 字节可能会更干净。

如果您的实施在速度方面令人满意,那么我想就是这样。否则,您可以研究如何管理数据库。在这种情况下,您将使用固定大小的缓冲区。最大的优点是您不会在许多小块中破坏内存并在以后遇到内存分配问题。同样在速度方面,您将分配这些块一次并多次重复使用它们。malloc()and函数很昂贵,free()特别是如果您有大量对象(new并且delete运算符调用这些函数)。

现在要节省更多内存,因为这听起来是主要目标,如果可能的话,您可以考虑使用 zlib 压缩字符串。我会使用最快的压缩模式,看看结果缓冲区是否更小,如果是,使用它。否则保留未压缩的字符串。这要求您为每个字符串保存一个大小(4 个字节)。当缓冲区未压缩时,您可以将大小设置为 0。

我想提到的另一件事是,使用非法字节可能会让未来维护该代码库的程序员感到困惑。无论您有多少评论,他们可能无论如何都不会阅读它们......你知道......程序员只是倾向于阅读代码,而不是评论。如果这是您担心的事情,您可以将连接的字符串保存在向量中。您的 split 函数将 char 向量作为输入并返回字符串向量作为其结果。

另一种可能性是通过mmap(). 但是,在处理动态数据时,这可能很乏味。这就是类似数据库的方案非常有用的地方。您将分配块(即一次 64Kb)并在每个块的基础上管理您的数据。当一个字符串对于当前块来说变得太大时,将它移动到一个新块......这种技术的优点是数据保留在内存中,除非操作系统决定它需要你的软件正在使用的一些 RAM 并且它可以随时换掉。对你来说,这种交换将是完全透明的。它还比使用默认交换要快得多,默认交换必须以低效率的方式管理您的内存。


推荐阅读