std :: string是如何实现的?

我很好奇知道std :: string是如何实现的,它与c string有什么不同?如果标准没有指定任何实现,那么任何解释的实现都会如何满足标准给出的string要求呢?

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

Scott Meyer的书Effective STL有一章关于std :: string的实现,这是对常见变体的一个体面的概述:“Item 15:注意string实现中的变化”。

他谈到了4个变化:

  • ref-count实现的一些变化(通常称为copy on write) – 当一个string对象被拷贝不变时,refcount递增,但是实际的string数据不是。 两个对象都指向相同的引用数据,直到其中一个对象修改它为止,导致数据的“写入时复制”。 这些变化是在像refcount,锁等存储的地方。

  • 一个“短string优化”(SSO)实现。 在这种变体中,对象包含通常的指向数据的指针,长度,dynamic分配的缓冲区的大小等。但是如果string足够短,将使用该区域来保存string,而不是dynamic分配缓冲区

另外, Herb Sutter的“More Exceptional C ++”有一个附录(附录A:“不在multithreading世界中的优化”),讨论了为什么在写入引用的实现上复制通常由于同步问题而在multithreading应用程序中出现性能问题。 那篇文章也可以在网上find(但是我不确定它和书中的内容是否完全一样):

这两章都值得一读。

std :: string是一个包装某种内部缓冲区的类,并提供了处理该缓冲区的方法。

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

解释std :: string在这里工作的所有细节将需要很长的时间。 也许看看gcc的源代码http://gcc.gnu.org看看他们究竟是怎么做的。;

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

另外,假设你安装了gcc,你可以看看gcc的实现。 如果没有,您可以通过SVN访问他们的源代码 。 大部分std :: string是由basic_string实现的,所以从这里开始。

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

string的c ++解决scheme与c版本完全不同。 第一个也是最重要的区别是,使用ASCIIZ解决scheme的c,std :: string和std :: wstring使用两个迭代器(指针)来存储实际的string。 string类的基本用法提供了一个dynamic分配的解决scheme,所以以dynamic内存处理的CPU开销为代价,使得string处理更加舒适。

正如您可能已经知道的,C不包含任何内置的通用stringtypes,只通过标准库提供几个string操作。 C和C ++之间的主要区别之一就是C ++提供了一个包装function,所以它可以被看作是一个伪造的genericstypes。

在C中,如果你想知道它的长度,你需要遍历string,std :: string :: size()成员函数基本上只是一个指令(end – begin)。 只要你有内存,你可以安全地将string追加到另一个string中,所以不需要担心缓冲区溢出错误(也就是漏洞利用),因为如果需要的话,追加会创build一个更大的缓冲区。

正如有人在此之前所说,string是从vectorfunction派生的,以模板的方式,因此更容易处理多字节字符系统。 你可以使用typedef std :: basic_string specific_str_t定义你自己的stringtypes; expression式与模板参数中的任意任意数据types。

我认为双方都有足够的优点和缺点:

C ++string优点: – 在某些情况下迭代速度更快(明确地使用大小,并且不需要来自内存的数据来检查是否在string末尾,比较两个指针,这可能会影响caching) – 缓冲区操作与stringfunction打包在一起,所以不用担心缓冲区问题。

C ++string缺点: – 由于dynamic内存分配的原因,基本的使用可能会对性能造成影响。 (幸运的是,你可以告诉string对象应该是什么原始的缓冲区大小,所以除非你超过它,它将不会从内存中分配dynamic块) – 与其他语言相比,通常是怪异和不一致的名字。 这对任何stl的东西都是坏事,但是你可以使用它,并且使得它具有特定的C ++ ish感觉。 – 模板的大量使用迫使标准库使用基于头的解决scheme,因此对编译时间产生很大的影响。

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

例如, STLPort是一个C ++标准库实现,它实现了string等等。