GCC的std::string - 为什么实现如此奇怪

4
当我在查看gcc中std :: string的实现方式时,我注意到sizeof(std :: string)恰好等于指针的大小(在x32构建中为4个字节,在x64中为8个字节)。由于字符串应至少包含指向字符串缓冲区和其长度的指针,这使我认为GCC中的std :: string对象实际上是指向某个内部结构的指针,该结构保存此数据。
因此,即使字符串为空,创建新字符串也应进行一次动态内存分配。
除了性能开销外,这还会导致内存开销(当我们分配非常小的内存块时发生)。
因此,我只看到了这种设计的劣势。我错过了什么?有哪些优点,以及首先采用这种实现方式的原因是什么?

2
对于我自己而言,我通常认为编译器和标准库的作者在设计时考虑得比我更周全。除非我遇到了可能由此引起的具体问题,否则我会默认这些设计都有其合理性。现在,你可能是出于好奇在问这个问题。如果是这样,我建议你自己做更多的研究——源代码和其存储库就在那里 :) - Magnus Hoff
3
GCC的std::string是一种实现为智能指针的写时复制技术,指向实际缓冲区的字符串类型。由于其开源,因此您可以直接阅读相关代码。 - Jan Hudec
谢谢,Jan,我应该自己找到这个的。请发布为答案,我会接受。 - Alex Z
1个回答

5
请阅读<bits/basic_string.h>中顶部的长注释,它解释了指针指向何处以及字符串长度(和引用计数)存储在哪里以及为什么要这样做。然而,C++11不允许使用引用计数的写时复制std::string,因此GCC实现将不得不更改,但这样做会破坏ABI,因此被推迟到ABI变化不可避免的时候。我们不想改变ABI,然后几个月后再次改变它,然后再次改变它。当它发生变化时,应该只改变一次,以最小化用户的麻烦。

这方面有任何更新吗?ABI的更改是否可预见?它能否有条件地启用? - Kerrek SB
1
这种变化可能会发生在GCC 4.9中,只有使用C++11时才会生效。 - Jonathan Wakely
2
@KerrekSB C++11 ABI的变化发生在GCC 5.1中:https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html(并且有一个宏可以定义以保留旧的ABI,即使是今天的GCC 8.x)。 - John Zwinck

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