std::string是如何实现的?

62

我很想知道std::string是如何实现的,它与c字符串有何不同?如果标准没有指定任何实现,则任何带有说明的实现都会很好,说明它如何满足标准给出的字符串要求。


12
你可能需要获取类似gcc的源代码,看一下它们是如何实现的。 - James Black
1
相关:https://dev59.com/Ak7Sa4cB1Zd3GeqP69WK - user649198
5个回答

82
几乎我使用过的每个编译器都提供了运行时源代码 - 所以无论您使用GCC、MSVC还是其他编译器,您都可以查看实现。然而,std::string的大部分或全部将被实现为模板代码,这可能会使阅读变得非常困难。 Scott Meyer的书《Effective STL》有一章关于std::string实现的概述:"Item 15: Be aware of variations in string implementations"。
他谈到了4种变体:
- 几种基于引用计数的实现(通常称为写时复制) - 当一个字符串对象被无改变地复制时,引用计数会增加,但实际的字符串数据不会。两个对象指向相同的引用计数数据,直到其中一个对象修改它,导致数据的“写时复制”。变体在存储引用计数、锁等方面有所不同。 - 一种“短字符串优化”(SSO)实现。在这个变种中,对象包含通常的指向数据、长度、动态分配缓冲区的大小等指针。但如果字符串足够短,则会使用该区域来保存字符串,而不是动态分配缓冲区。
此外,Herb Sutter的《更多的异常C ++》有一个附录(附录A:“在多线程世界中不适用的优化”),讨论了为什么写时复制引用计数实现在多线程应用程序中经常存在性能问题,原因是同步问题。该文章也可以在线获取(但我不确定是否与书中内容完全相同):

这两个章节都值得阅读。


2
注意(因为它与最近的问题相关):有趣的是,GCC的写时复制实现在移动情况下比VC++短字符串优化表现更好,因为移动操作主要受到对象的sizeof影响。 - Matthieu M.
“短字符串优化”显然经常被缩写为“SSO”:https://dev59.com/O2kv5IYBdhLWcg3w1kSq - Raedwald
我认为Scott Meyers和Herb Sutter的书籍包含了关于字符串实现的很好的通用信息,但它们并没有明确说明哪些实现使用了哪些优化(或非优化)。如果你想知道这个,可以在这里进行比较:http://info.prelert.com/blog/cpp-stdstring-implementations。 - dmr195
gcc的实现在这里:https://gcc.gnu.org/onlinedocs/gcc-4.8.1/libstdc++/api/a01053_source.html - Yiannis Mpourkelis

15

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

C语言中的字符串只是字符数组。

在这里解释std::string如何工作的所有细节需要太长时间。也许可以查看gcc源代码http://gcc.gnu.org来确定它们如何实现。


8

5

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

正如您可能已经知道的那样,C不包含任何内置的通用字符串类型,只通过标准库提供了一些字符串操作。C++提供了一个封装功能,所以它可以被认为是一个伪通用类型。

在C中,如果您想知道字符串的长度,您需要遍历字符串,而std::string::size()成员函数只需要一条指令(end - begin)。只要有内存,您就可以安全地将字符串追加到另一个字符串中,因此无需担心缓冲区溢出错误(因此也没有漏洞),因为追加会在需要时创建更大的缓冲区。

正如某人在这里之前说过的那样,字符串是从向量功能派生出来的,以模板方式进行,因此更容易处理多字节字符系统。您可以使用typedef std::basic_string specific_str_t;表达式定义自己的字符串类型,其中任意数据类型都可以作为模板参数。

我认为双方有足够的利弊:

C++字符串优点: - 在某些情况下迭代速度更快(明确使用大小,它不需要从内存中获取数据来检查您是否到达了字符串的末尾,比较两个指针。这可能会在缓存方面产生差异) - 缓冲区操作与字符串功能打包在一起,因此对缓冲区问题的担忧较少。

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


3
这取决于你使用的标准库。
例如,STLPort是一个实现了字符串等内容的C++标准库实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接