关于c ++:如何实现std :: string?

How is std::string implemented?

我很想知道STD::字符串是如何实现的,它是如何与C字符串不同的?如果标准没有指定任何实现,那么任何带解释的实现都将很好地满足标准给出的字符串要求?


实际上,我使用的每一个编译器都为运行时提供了源代码——因此,无论您使用的是gcc还是msvc,您都有能力查看实现。但是,大部分或全部的std::string将作为模板代码实现,这会使读取非常困难。

Scott Meyer的书,有效的STL,有一个关于STD::String实现的章节,它是对常见变化的一个体面的概述:"项目15:注意EDCOX1和1实现中的变化"。

他谈到了4种变化:

  • 引用计数的实现(通常称为"写入时复制")上的几个变体-当字符串对象被复制为未更改时,引用计数将增加,但实际的字符串数据不会增加。两个对象都指向相同的refcounted数据,直到其中一个对象对其进行修改,从而导致数据的"写入时复制"。这些变化包括存储refcount、锁等内容的位置。

  • "短字符串优化"(SSO)实现。在这个变量中,对象包含指向数据、长度、动态分配缓冲区大小等的普通指针。但是,如果字符串足够短,它将使用该区域来保存字符串,而不是动态分配缓冲区。

此外,Habor萨特的"更优秀的C++"有一个附录(附录A:"不是在多线程世界中的"),它讨论了为什么由于同步问题,在多线程应用程序中,复制写点数的实现常常会出现性能问题。这篇文章也可以在线阅读(但我不确定它是否与书中的完全相同):

  • http://www.gotw.ca/publications/optimizations.htm(http://www.gotw.ca/publications/optimizations.htm)

这两章都值得一读。


STD::String是一种封装某种内部缓冲区的类,并提供操作该缓冲区的方法。

C中的字符串只是一个字符数组

解释STD::String在这里工作的所有细微差别需要花费太长时间。也许可以看看gcc源代码http://gcc.gnu.org,看看它们是如何做到的。


在本页的答案中有一个示例实现。

此外,您可以查看gcc的实现,假设您已经安装了gcc。如果没有,您可以通过SVN访问它们的源代码。STD::字符串是用Basic字符串实现的,所以从那里开始。

另一个可能的信息来源是watcom的编译器


字符串的C++解决方案与C版本有很大的不同。STD:STR::String:和STD::WString使用两个迭代器(指针)来存储实际的字符串。字符串类的基本用法提供了一个动态分配的解决方案,因此在动态内存处理的CPU开销成本中,它使字符串处理更加舒适。

正如您可能已经知道的,C不包含任何内置的泛型字符串类型,只通过标准库提供了几个字符串操作。C和C++之间的主要区别之一是C++提供了一个封装的功能,因此它可以被认为是伪造的泛型类型。

在C中,你需要遍历字符串,如果你想知道它的长度,STD:::Stry::siz()函数基本上只有一个指令(结束-开始)。只要有内存,就可以安全地将字符串一个附加到另一个,因此不必担心缓冲区溢出错误(因此也不必担心漏洞),因为如果需要,附加会创建更大的缓冲区。

如前所述,字符串是以模板化的方式从向量功能派生出来的,因此处理多字节字符系统更容易。可以使用TyPulf STD::Basic字符串String OpjyStryt定义自己的字符串类型;模板参数中任意任意数据类型的表达式。

我认为双方都有足够的优势和劣势:

C++字符串PROS:-在某些情况下更快的迭代(一定要使用大小,并且不需要从内存中获取数据来检查是否在字符串的末尾,比较两个指针。这可能会对缓存产生影响)-缓冲区操作使用了字符串功能,因此不必担心缓冲区问题。

C++字符串错误:-由于动态内存分配的原因,基本的使用可能会对性能造成影响。(幸运的是,您可以告诉字符串对象什么是原始缓冲区大小,所以除非您超过了它,否则它不会从内存中分配动态块)-与其他语言相比,名字常常怪异且不一致。这是任何STL的坏东西,但你可以使用它,它有点特殊的C++感觉。-模板的大量使用迫使标准库使用基于头的解决方案,因此这对编译时间有很大的影响。


这取决于您使用的标准库。

例如,STLPART是一个C++标准库实现,它实现了其他方面的字符串。