#include <string>
static_assert(sizeof(std::string) != sizeof(void*), "using ref-counted string");
int
main()
{
}
演示:http://melpon.org/wandbox/permlink/P8LB79Cy6ASZlKuV
此测试利用std::string 的所有已知 std::lib 实现的内部工作原理,尤其是 gcc 的实现。
gcc 的引用计数string 由一个指向动态分配结构的指针组成,该结构保存字符串的大小、容量、引用计数和数据。 Scott Meyers 对 Effective STL 中的字符串实现做了一个很好的总结,在 2001 年的时间框架内是准确的。我相信(我可能弄错了)那本书第 15 项中的“实现 C”是 gcc 的 std::string。
对于短字符串实现(C++11 几乎强制要求),string 不能再由堆栈上的单个指针组成。 Scott 的实现 D 是我们第一次看到那个时代的短字符串实现。这是 VS/Dinkumware string。 sizeof(string) 本身将包含一些数据缓冲区来保存没有分配的字符串数据。
人们可以通过这个简短的程序了解不同的实现正在做什么:
#include <iostream>
#include <string>
int
main()
{
std::string s;
std::cout << "word size is " << sizeof(void*)/sizeof(char) << '\n';
std::cout << "sizeof string is " << sizeof(s) << '\n';
std::cout << "short string buffer is " << s.capacity() << '\n';
}
这会打印出字长,通常为 4 或 8(32 位 / 64 位),因为至少有一个实现 (libc++) 在此硬件功能上更改了其特性。然后它打印出sizeof(string),它将是字长的倍数,然后是空的string 的capacity(),如果它存在,它将是短字符串缓冲区的大小。
这是一个有些不完整的调查:
gcc/libstdc++ 4.8
word size is 8
sizeof string is 8
short string buffer is 0
gcc/libstdc++ 5.2
word size is 8
sizeof string is 32
short string buffer is 15
clang/libc++ -arch i386 OS X
word size is 4
sizeof string is 12
short string buffer is 10
clang/libc++ -arch x86_64 OS X
word size is 8
sizeof string is 24
short string buffer is 22
VS-2015
word size is 4
sizeof string is 24
short string buffer is 15
在这次调查中,只有 gcc/libstdc++ 4.8 显然没有使用短字符串优化。只有 gcc/libstdc++ 4.8 有sizeof(string) == 1 word。这实际上是本次调查中唯一使用引用计数的实现。
总而言之,这个针对 libstdc++ 的std::string 的测试是不可移植的。但根据规范,它不一定是。我们可以利用已知的 gcc 在这一领域的发展历史。规范(问题)说它只需要在 gcc 的 libstdc++ 上工作。