如何实现std :: string?

yes*_*aaj 53 c++ string std cstring

我很想知道如何实现std :: string以及它与c字符串的区别?如果标准没有指定任何实现,那么任何带有解释的实现都会很好,它如何满足标准给出的字符串要求?

Mic*_*urr 73

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

Scott Meyer的书,Effective STL,有一章关于std :: string实现,这是对常见变体的一个不错的概述:"第15项:注意string实现中的变化".

他谈到了4种变化:

  • 关于引用计数的实现的几种变体(通常称为写入时的复制) - 当字符串对象未被更改时,refcount会递增,但实际的字符串数据不会.两个对象都指向相同的refcounted数据,直到其中一个对象修改它,导致数据的"写入时复制".这些变化存在于诸如引用计数,锁等之类的位置.

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

另外,Herb Sutter的"更多例外C++"有一个附录(附录A:"不是(在多线程世界中)的优化"),讨论了为什么复制写入refcounted实现由于同步问题在多线程应用程序中经常出现性能问题.那篇文章也可在线获取(但我不确定它是否与书中的内容完全相同):

这两章都值得一读.

  • 注意(因为从最近的问题链接):有趣的是,GCC的写入实现执行复制比*move*情况下的VC++短字符串优化更好,因为*move*操作主要受`sizeof`对象的影响. (2认同)

Gle*_*len 12

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

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

解释std :: string如何在这里工作的所有细微差别将花费太长时间.也许看一下gcc源代码http://gcc.gnu.org,看看他们究竟是怎么做的.


DVK*_*DVK 6

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

此外,假设您已安装gcc,您可以查看gcc的实现.如果没有,您可以通过SVN访问他们的源代码.大多数std :: string是由basic_string实现的,所以从那里开始.

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


小智 5

字符串的 C++ 解决方案与 C 版本有很大不同。第一个也是最重要的区别是 c 使用 ASCIIZ 解决方案,而 std::string 和 std::wstring 使用两个迭代器(指针)来存储实际字符串。字符串类的基本用法提供了动态分配的解决方案,因此动态内存处理的 CPU 开销成本使字符串处理更加舒适。

您可能已经知道,C 语言不包含任何内置的通用字符串类型,仅通过标准库提供一些字符串操作。C 和 C++ 之间的主要区别之一是 C++ 提供了包装功能,因此可以将其视为伪造的泛型类型。

在 C 中,如果您想知道字符串的长度,则需要遍历字符串,std::string::size() 成员函数基本上只是一条指令(结束 - 开始)。只要有内存,您就可以安全地将字符串一个接一个地追加,因此无需担心缓冲区溢出错误(以及漏洞利用),因为追加会在需要时创建更大的缓冲区。

正如有人之前所说,字符串是以模板化方式从向量功能派生的,因此更容易处理多字节字符系统。您可以使用 typedef std::basic_string Specific_str_t; 定义自己的字符串类型。模板参数中具有任意数据类型的表达式。

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

C++ 字符串优点: - 在某些情况下迭代速度更快(明确使用大小,并且不需要内存中的数据来检查是否位于字符串的末尾,比较两个指针。这可能会与缓存) - 缓冲区操作包含字符串功能,因此不用担心缓冲区问题。

C++ 字符串 缺点: - 由于动态内存分配的问题,基本使用可能会对性能造成影响。(幸运的是,您可以告诉字符串对象原始缓冲区大小应该是多少,因此除非超出它,否则它不会从内存中分配动态块) - 与其他语言相比,名称通常很奇怪且不一致。这是任何 stl 东西的坏处,但你可以使用它,并且它给人一种特定的 C++ 感觉。- 模板的大量使用迫使标准库使用基于标头的解决方案,因此这对编译时间有很大影响。