C++11起std::string内存连续但含SSO和预留空间,而std::vector严格物理连续且无字符串语义约束;二者不可互换使用。
在 C++11 标准之前,std::string 的实现允许使用“写时复制”(Copy-on-Write),底层缓冲区甚至可能被多个 std::string 对象共享,此时 &str[0] 不一定指向真正可写的连续区域。C++11 明确要求 std::string 必须满足“连续存储”——即 &str[0] + i == &str[i] 对所有有效 i 成立,但该连续块仍可能包含未使用的预留空间(capacity() ≥ size()),且其起始地址不一定等于堆分配的原始指针(例如 small string optimization 会把短字符串存在对象内部)。
std::string 对象的栈内字段中,&str[0] 指向对象内部偏移,不是堆地址std::string::data() 和 &str[0] 在非空时等价,但空字符串下 &str[0] 是未定义行为,必须用 data()
std::vector 的标准要求其元素必须存储在单一、动态分配的连续内存块中,且 &v[0] 等价于 v.data()(只要 v.size() > 0)。这个连续性是强制的、可依赖的,也是它支持传给 C 接口(如 read(fd, v.data(), v.size()))的根本原因。
int、char 还是自定义结构体,std::vector 的 T 实例在内存中逐个紧邻排列
int,也会发生一次堆分配(除非使用自
表面看都是字符容器,但二者抽象层级和内存契约不同。你无法安全地对 std::string 做 resize() 后直接用 data() 当裸缓冲区填入二进制数据,因为:
data() 返回的是对象内部地址,大小受限且不可 reallocstd::string 的逻辑长度(size())与缓冲区实际可用长度(capacity())分离,修改 data()[i] 不自动更新 size()
std::string 有隐式 null 终止要求(c_str() 返回值以 \0 结尾),而 std::vector 完全无此约束std::string s; s.resize(10); // size=10, capacity≥10 s[0] = 'x'; // OK,但 s 仍是合法字符串 // 若后续调用 s.c_str(),它保证返回以 \0 结尾的 C 字符串 // 这个 \0 可能位于 s[10](额外分配的字节),也可能复用 capacity 中的闲置位置
取决于用途:
append()/find() 等语义 → 用 std::string,但别绕过其接口直接操作底层内存std::vector 或 std::vector<:byte>(C++17)std::string 的 SSO,但别假设其 layout 可跨平台移植最易被忽略的一点:std::string 的连续性是“逻辑连续”,而 std::vector 的连续性是“物理+语义连续”。前者服务于字符串语义,后者服务于通用容器契约。混用它们的底层指针,迟早会在某个编译器或 STL 版本上出问题。