libstdc++ 和 libc++ 中字符串倍增比较

https://godbolt.org/z/n8hns47M8

#include <iostream>
#include <string>

int main() {
  std::string str = "hello";
  std::cout << "String: \"" << str << "\"" << std::endl;
  std::cout << "Length: " << str.length() << std::endl;
  std::cout << "Capacity: " << str.capacity() << std::endl;
  std::cout << "Size: " << sizeof(str) << std::endl;

  str += " world!。。。。";
  std::cout << "\nString: \"" << str << "\"" << std::endl;
  std::cout << "Length: " << str.length() << std::endl;
  std::cout << "Capacity: " << str.capacity() << std::endl;
  std::cout << "Size: " << sizeof(str) << std::endl;

  str += str;
  std::cout << "\nString: \"" << str << "\"" << std::endl;
  std::cout << "Length: " << str.length() << std::endl;
  std::cout << "Capacity: " << str.capacity() << std::endl;
  std::cout << "Size: " << sizeof(str) << std::endl;
  return 0;
}

可以看到 libstdc++ 中的 capacity 的增长方式是 15 → 30 → 60。一开始 SSO 缓冲区只能容纳 16 个字符,最后一个字符是 '\0',因此初始状态下只能容纳 15 个非空字符,capacity 为 15。而后面倍增的时候会直接按照非 '\0' 字符的最大容量来做倍增,而非按照实际缓冲区容量做倍增(即 15 → 31 → 63 这样的路径)。

而 libc++ 中 capacity 的后续倍增是考虑了空字符的:22 → 47 → 95。一开始并不是按照缓冲区容量 23 去倍增,而是用的 24,可能是认为 23 这个数字不够规整。