用C ++设计字符串类

时间:2010-08-30 11:00:00

标签: c++ string

我需要在C ++中设计(并在某些时候编写代码)“自定义”字符串类。我想知道你能不能让我知道任何文件和设计问题,主要是我应该注意的潜在缺陷。非常欢迎链接,以及使用当前字符串库(Qstring,std :: string和其他)识别问题(如果有)。

谢谢。

7 个答案:

答案 0 :(得分:14)

尽管有批评者,我认为这是一个有效的问题。

std::string不是灵丹妙药。看起来有人从纯OO中取出类并将其转储到C ++中,这可能就是这种情况。

建议1:首选非会员非朋友方法

既然如此,在国际化的这个时刻,我肯定会建议你设计一个支持Unicode的课程。我确实说过Unicode,而不是UTF-8UTF-16。我认为设计一个包含给定编码数据的类是不合适的(我认为)。您可以提供方法,然后以各种格式输出信息。

建议2 支持Unicode

然后,内存分配方案有很多要点:

  • 小字符串优化:该类包含几个字符(十二个或两个)的预分配空间,从而避免为这些字符分配堆
  • Copy On Write:各种字符串共享一个缓冲区,以便副本便宜,当一个字符串需要修改其内容时,如果它不是唯一所有者,则复制缓冲区 - >问题是多线程在这里引入了开销,并且已经证明,对于通用技术而言,这种开销可能使实际复制成本相形见绌
  • 不可变性:JavaC#Python等“新”语言使用不可变字符串。可以把它想象成一个字符串池,所有包含“Fooo”的字符串都指向同一个缓冲区。请注意,这些语言支持垃圾收集,这对此有帮助。

我个人会在这里选择“小字符串优化”(虽然它并不与其他两个一起使用),只是因为它实现起来很简单并且实际上应该让你受益(堆分配成本,参考问题的位置)。

另外两种技术在面对多线程时有些复杂,而且很容易出错,除非精心制作,否则不太可能带来任何实际好处。

这带来了我的最后建议:

建议3 :在尝试MultiThreading支持时不要实现内部锁定

在SingleThreaded上下文中使用它会减慢类的速度,并且在使用MultiThreaded时不会产生那么多的好处。

最后,您可以通过浏览现有代码找到适合您口味(或获得一些指示)的内容。我不承诺展示“流畅”的界面:

  • ICU UnicodeString:Unicode支持,至少
  • std::string:超过100个成员方法(计算各种重载)
  • llvm StringRef:注意有多少算法作为成员方法实现:'(

答案 1 :(得分:3)

Scott Meyers的

Effective STL对可能的std::string实现技术进行了一些有趣的讨论,但它涵盖了相当高级的问题,例如写时复制和引用计数。

答案 2 :(得分:2)

根据“自定义”的内容(例如自定义分配器),您可以通过std :: basic_string类的模板参数来完成。

答案 3 :(得分:2)

Herb Sutter在GotW #29中提供了自定义字符串类的示例。你可以在开始时使用它。

答案 4 :(得分:1)

从通用的角度来看,“新”字符串类理想地结合了std :: string,CString,QString等的优点。以随机顺序排列的几点:

  • 由于非常具体的实现,MFC CString支持在类似printf的函数中使用它。 如果您需要或想要此功能,我建议您购买George Sheperd撰写的“MFC Internals”一书。虽然这本书是从1996年开始的(!),但它对CString如何实现的描述应该是值得的。 http://www.amazon.com/MFC-Internals-Microsoft-Foundation-Architecture/dp/0201407213/ref=sr_1_1?ie=UTF8&s=books&qid=1283176951&sr=8-1
  • 检查您的字符串类是否与您将使用它的所有接口(iostreams,Windows API,printf *等)完美匹配
  • 不要瞄准完整的unicode支持(如:collat​​ion,grapheme clusters,......)因为这意味着你的类永远不会被完成,但考虑将它变成带有转换选项的wchar_t类。
  • 考虑使用char *创建字符串对象的ctor / function始终采用字符数组的特定编码。 (在混合UTF-8 /其他字符集环境中可能会有所帮助。)
  • 查看完整的CString接口和完整的std:string接口,确定您需要的内容以及可以跳过的内容。
  • 看看QString,看看其他两个错过了什么。
  • 不提供对char / wchar_t *
  • 的隐式转换
  • 考虑在数字类型中添加方便的转换函数。
  • 如果没有完整的详细单元测试,请不要编写字符串类!

答案 5 :(得分:0)

世界不需要另一个字符串类。这是家庭作业吗?如果没有,请使用std::string

答案 6 :(得分:0)

std :: string的问题是..你无法改变它。有时您需要std :: string的基础知识,但不同意c ++库的实现。

例如,使用线程安全引用计数意味着大量锁定(或至少锁定操作)。此外,如果您的大多数字符串都很短(因为您知道会出现这种情况),您可能需要一个针对该用例进行优化的字符串类。

因此,即使您喜欢std :: string API,或者至少已经学会了它,但仍有“竞争实施”的空间,或多或少都是相似的。

PowerDNS希望拥有一个,因为我们目前传递了许多dns主机名,并且其中绝大多数都适合于25字节的固定缓冲区,这将减轻许多新的/删除压力。 / p>