C++
string的缺点
发布于 2026年7月22日
string的缺点
一、性能行为:可预测,但容易踩坑
最常被吐槽的是拷贝开销。
string在对象内部塞一块小缓冲区,短字符串直接存栈上,零堆分配。64 位系统上,GCC 阈值是 15 字节,Clang 是 22 字节。
#include <iostream>
#include <string>
#include <cstdlib>
void* operator new(std::size_t size)
{
std::cout << "malloc " << size << "\n";
return malloc(size);
}
int main()
{
std::string s1 = "hello"; // 5 字节 → 无分配
std::string s2 = "a string longer than 15"; // 超过阈值 → malloc
}
输出:
malloc 32
SSO 救得了短字符串,但救不了中长字符串的频繁拼接:
void* operator new(std::size_t size)
{
std::cout << "malloc " << size << "\n";
return malloc(size);
}
int main()
{
// 危险,可能多次realloc
std::string path;
for (size_t i = 0; i < 255; i++)
{
path += "/";
}
}
输出:
malloc 32
malloc 48
malloc 71
malloc 106
malloc 158
malloc 236
malloc 353
好的做法是提前reserve:
path.reserve(255); // 一次性分配,避免 realloc
C++17 之前,substr() 总是返回新 string,就是完整拷贝:
void parse(const std::string& line) {
auto key = line.substr(0, 5); // 就算只读,也拷贝 5 字节
}
直到 C++17 引入 std::string_view,才做到的零拷贝
void parse(std::string_view line) {
auto key = line.substr(0, 5); // 零拷贝,仅指针+长度
}
但新的坑又来了,产生了未定义行为:
std::string_view bad() {
std::string s = "local";
return s; // s 析构后,view 悬空
}
二、功能缺失:它是容器,不是文本工具
别被 std::string 的名称给骗了,它根本不是为文本设计的,它就是个 vector<char>,只不过多了几个字符串方法。
你往里面放 UTF-8,它会当字节来存。
你调用length() ,它返回的是字节数,不是字符数。
std::string emoji = "👋🌍"; // UTF-8,共 8 字节
std::cout << emoji.length(); // 输出 8