跨平台字符串类实现良好的模型可移植性"Best Practices"是什么?

What are "Best Practices" for a Cross-Platform string class to implement good model portability?

本文关键字:可移植性 Best Practices 是什么 模型 字符串 实现 跨平台      更新时间:2023-10-16

关于跨平台Unicode字符串使用的主题有无数的讨论线程,但似乎有广泛的意见,没有解决一些特定的问题,这些问题一直困扰着我在一个特定的项目中工作:

我有一个很大的跨平台c++代码库,可以追溯到近20年前。它包含了各种类型的字符串实现,包括:

  • char*
  • Pascal-style字符串
  • std::string
  • 具有重叠功能的多个自定义跨平台类
  • CFString
  • 各种类型的常量字符串

这个代码库正在被重写,以完全使用Unicode字符串和实现一个强大的MVC架构,希望模型将是完全可移植的(Mac OS/IOS/Android/Windows 7 &8/Unix).

当持久数据被写入XML/UTF-8时,在运行时对象中使用字符串存在一些困境:

  1. 我想创建一个类,干净地隐藏存储,分配和常见的字符串操作的实现。通过c++操作符和赋值重载的奇迹,我希望能够替换一个类实例来替换函数可以接受的所有不同的字符串参数。这将允许代码库的增量转换。

  2. 我们不断地扫描/解析/分析字符串,我担心对持久对象使用严格的UTF-8底层实现可能会有性能问题。如果不是,在微软的vc++和GNU的g++中发现的现代std::string是不是一个简单的底层实现?

  3. Mac OS/IOS版本最终需要将它们的字符串"转换"为CFString。CF函数丰富且高度优化。我认为这将是一个很好的策略,让我自己的类通过提供CF与缓冲区创建CFStrings(例如,CFStringCreateWithCharactersNoCopyCFStringCreateMutableWithExternalCharactersNoCopy)。似乎这可以减少转换/分配CFString通常需要从模型中获取数据后的数量-虽然也许在一个适当的MVC实现控制器/视图不应该访问模型拥有的实际字符串?

  4. c++ 11是否改变了这些跨平台字符串问题的情况?

我本以为这些问题早就应该解决了——但是从这个网站(和其他网站)上的回复来看,我看不出有什么问题。

我想创建一个类,干净地隐藏存储,分配和常见的字符串操作的实现。通过c++操作符和赋值重载的奇迹,我希望能够替换一个类实例来替换函数可以接受的所有不同的字符串参数。这将允许代码库的增量转换。

听起来像std::string,添加了对const char*的强制转换操作符,所以您不必调用c_str()。这就意味着你必须使用char和UTF-8来存储,而不是使用UTF-16或类似的格式。

我们不断地扫描/解析/分析字符串,我担心对持久对象使用严格的UTF-8底层实现可能会有性能问题。如果不是,在微软的vc++和GNU的g++中发现的现代std::string会是一个简单的底层实现吗?

这取决于其他几个因素。一方面,如果输入包含大量非ascii数据,并且必须一次分析一个代码点,那么UTF-8 可能会效率低下。在这种情况下,UTF-16甚至UTF-32可能更合理,因为您不会有太多的大小写差异来重新组装来自多个字符串元素的代码点。另一方面,性能在很大程度上取决于您是可以通过引用传递字符串还是必须创建副本,特别是在调用函数时。因此,为了避免过多的副本,对现有代码库进行一些修改可能是必要的。

Mac OS/IOS版本最终需要将其字符串"转换"为CFString。CF函数丰富且高度优化。我认为这将是一个很好的策略,让我自己的类通过提供CF与缓冲区创建CFStrings(例如,CFStringCreateWithCharactersNoCopy或CFStringCreateMutableWithExternalCharactersNoCopy)。似乎这可以减少转换/分配CFString通常需要从模型中获取数据后的数量-虽然也许在一个适当的MVC实现控制器/视图不应该访问模型拥有的实际字符串?

当您创建字符串而不复制数据缓冲区时,那么您必须确保只要字符串被访问,缓冲区就存在。这在某些情况下可能是正确的,但并非所有情况都是如此。一般来说,这些问题与由std::string支持的char*非常相似,这就是为什么c_str()是显式函数调用而不仅仅是自动强制转换的原因。通过进行这样的转换,必须保证原始对象保持已分配状态。一般来说,我会将const std::string&传递给视图,这样它们就不会意外地改变模型拥有的字符串。如果他们需要保留或修改字符串,他们必须复制它。

c++ 11是否改变了这些跨平台字符串问题的图景?

c++ 11提供了许多新的智能指针实现,允许你更好地控制字符串对象的分配时间。因此,例如,您可以使用shared_prt<string>作为类的数据存储,以获得自动引用计数和字符串的释放。这将为您提供更高层次的抽象,但可能与您当前的代码库所做的工作相去甚远,因此我不确定这是否会使移植更容易。