

新闻资讯
技术百科c_str() 返回的指针不能长期持有c_str() 返回的是 const char*,指向内部缓冲区的只读 C 风格字符串。但这个指针**不拥有内存所有权**,且其有效性完全依赖于原 std::string 对象的生命期和是否被修改。
string 被析构、移动(move)、或发生任何可能触发重新分配的操作(如 push_back()、+=、resize()),该指针立即悬空(dangling)s2 = s1;),s1.c_str() 仍有效;但若 s1.clear() 或 s1.append("x"),就可能失效string 会导致未定义行为c_str() 而不是 data()
C++11 起,std::string::data() 也返回 const char*,但语义不同:它不保证末尾有 \0;而 c_str() **严格保证以 \0 结尾,且返回值可安全传给 C 函数**(如 fopen()、printf()、strlen())。
strlen(s.data()) 是未定义行为(除非你刚手动补了 \0);但 strlen(s.c_str()) 总是安全的sqlite3_exec()、glShaderSource())必须用 c_str()
data() 更适合底层操作(如 memcpy 到二进制 buffer),c_str() 是“C 兼容接口”的明确契约c_str() 结
果存成成员变量或全局指针这是最典型的崩溃源头——把临时指针当成持久地址保存。
class Logger {
const char* last_msg_;
public:
void log(const std::string& s) {
last_msg_ = s.c_str(); // ❌ 悬空!s 是参数,退出函数即析构
printf("%s\n", last_msg_); // 可能打印乱码或 crash
}
};std::string 本身(推荐),或在需要时现场调用 c_str()
std::unique_ptr buf(new char[s.size()+1]); strcpy(buf.get(), s.c_str());
&s[0] 和 s.data() 在非空 string 下等价,但同样不带 \0 保证,不能替代 c_str()
c_str() 自 C++98 就存在,所有标准库实现都支持。C++20 加入了 std::string_view,它更轻量且明确只读,但不自动 null-terminate——所以 c_str() 在需要 C 接口时仍不可替代。
string_view 替换 c_str() 传给 printf("%s", sv.data()):缺少 \0 可能越界读取c_str() 可能触发一次小分配(罕见),但现代 libstdc++/libc++ 均为零开销error: cannot convert 'std::string' to 'const char*' in initialization,说明你漏写了 .c_str()
真正麻烦的从来不是怎么调用 c_str(),而是忘记它背后那个「瞬时有效」的契约——只要 string 变了,指针就废了。