在 std::string 中使用非法的 UTF-8 八位字节作为分隔符

Using an illegal UTF-8 octet as a delimiter in a std::string

本文关键字:八位 UTF-8 字节 分隔符 非法 string std      更新时间:2023-10-16

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

出于解释会误导的原因(见下文),我必须在单个字符串中存储多个 UTF-8 编码字符串。(字符串在这里表示C++std::string)

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

撇开有关性能的所有考虑因素不谈,这种方法是否存在我不知道的问题?有什么理由更喜欢其中一个非法八位组吗?

..

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

正如其他人提到的,使用任何适合您情况的字节都可以在std::string中正常工作。虽然如果你的字符串不使用'',使用这样的而不是非法的 UTF-8 字节可能更干净。

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

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

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

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