strcpy会崩,因为它只接受以'\0'结尾的C风格字符串,而std::string内部缓冲区不保证以'\0'结尾且C++11前不保证连续,直接传&str[0]或str.data()是未定义行为。

char[] 和 std::string 混用时,为什么 strcpy 会崩?
因为 strcpy 只认 C 风格字符串——以 '\0' 结尾的 char[],而 std::string 的内部缓冲区不保证以 '\0' 结尾(C++11 前甚至不保证连续),直接传 &str[0] 或 str.data() 给 strcpy 是未定义行为。
- 安全做法:用
str.c_str()获取只读、以'\0'结尾的 C 字符串指针 - 写入场景别硬套
strcpy:改用std::string::assign、+=或构造函数 - 如果必须操作底层内存(如对接 C API),先确保容量足够:
str.resize(n)再用&str[0],但记得手动补'\0'
什么时候该用 std::string_view 而不是 std::string?
当你只是「读」一段已存在的字符数据,且明确知道它的生命周期比当前作用域长——比如函数参数、配置解析、日志拼接中的字面量或临时字符串。
-
std::string_view不拥有内存,零拷贝,构造开销极小;std::string默认深拷贝 - 不能对
string_view调用append、resize等修改操作,它没有data()的可写权限 - 注意陷阱:传入局部
char[]或临时std::string的c_str()给string_view,会导致悬垂视图 - 典型签名:
void process(std::string_view sv),比const std::string&更通用也更轻量
std::string 的小字符串优化(SSO)到底省了什么?
省的是堆分配——当字符串长度 ≤ 实现定义的阈值(常见为 15 或 22 字节),std::string 直接把字符存进对象内部缓冲区,不 new 堆内存。
- 好处:短字符串高频创建/销毁时,避免 malloc/free 开销和缓存不友好
- 代价:对象尺寸变大(通常 24 或 32 字节),且 SSO 容量不可配置
- 别依赖具体长度:用
str.capacity()和str.data()地址是否等于&str来判断是否触发 SSO(仅作调试) - 长字符串仍走堆,SSO 不影响语义,也不解决内存碎片问题
从 char* 到 std::string 的隐式转换为什么被禁用了?
C++11 起,std::string 的 char* 构造函数加了 explicit,防止意外的隐式转换引发歧义或性能损耗。
立即学习“C++免费学习笔记(深入)”;
- 错误写法:
func("hello");若func接收std::string,以前会悄悄构造一个临时对象;现在编译失败 - 正确写法:显式构造
func(std::string("hello"))或用字面量后缀"hello"s(C++14) - 目的不是“禁止”,而是强制你意识到:这里发生了堆分配(哪怕很小),且有构造/析构开销
- 对接 C API 时尤其关键:别让隐式转换掩盖了所有权转移逻辑
SSO 的阈值、string_view 的生命周期、c_str() 的有效性——这些都不是文档里扫一眼就完的事,得在 core dump 或 ASan 报告里亲手撞过才记得住。










