直接用 std::string(cstr) 构造最常用,但需确保 cstr 非空指针、以 '\0' 结尾且内存合法;若已知长度 n,应使用 std::string(buf, n) 避免越界;std::string 总是深拷贝,但构造时源内存必须有效。
直接用 std::string 构造函数即可,但必须注意 char* 是否以 '\0' 结尾、是否为空指针、是否指向合法内存。
只要 char* 指向的是以 '\0' 结尾的 C 风格字符串(即 C-string),直接构造最简单:
char cstr[] = "hello"; std::string s(cstr); // ✅ 安全,自动识别长度
但如果传入的是空指针,会触发未定义行为(多数实现崩溃);如果传入非 null-terminated 数组(比如只存前 5 字节的二进制数据),std::string 会越界读直到遇到 '\0',结果不可控。
std::string(cstr)
nullptr 的 char* 直接构造,应先判空recv() 读取的字节数),用带长度的构造函数更可靠当你拿到的是一个原始 char 数组(比如 char buf[1024])和实际写入字节数 n,不能依赖结尾 '\0',必须显式传长度:
char buf[1024];
int n = recv(sock, buf, sizeof(buf)-1, 0);
if (n > 0) {
std::string s(buf, n); // ✅ 安全,只取前 n 字节
}这个构造函数不会扫描 '\0',而是严格按你给的长度截取。特别适合网络收包、文件读取、加密数据等场景。
'\0' 的二进制数据(比如图片头、JSON 片段)n 超出数组实际有效范围,仍是未定义行为char arr[] = "abc" 是栈上数组,const char* p = "abc" 是字面量(常量区),两者都能安全用于 std::string 构造——因为 std::string 会立即拷贝内容。
真正危险的是这种写法:
std::string bad() {
char local_buf[] = "temp";
return std::string(local_buf); // ✅ 拷贝了,没问题
}
// ✅ 上面其实 OK,因为 string 拷贝的是值,不是引用但如果你写成:
const char* get_cstr() {
char buf[] = "local";
return buf; // ❌ 返回局部数组地址,悬垂指针
}
std::string s(get_cstr()); // ❌ 此时 cstr 已失效,行为未定义std::string 总是深拷贝,不依赖源内存后续存活有人写 std::string s; s.assign(cstr); 或 s += cstr;,功能上等价,但多一次默认构造 + 赋值,无必要:
char cstr[] = "hello"; std::string s1(cstr); // ✅ 一步到位,高效 std::string s2; s2.assign(cstr); // ⚠️ 多一次空字符串构造和内存分配 s2 += cstr; // ⚠️ 同样,先空构造再追加
除非你需要复用已有 string 对象(比如循环中反复赋新值),否则直接构造更清晰、更高效。
assign 和 operator+= 在已有容量不足时可能触发额外 reallocstd::string_view,但它不是 std::string
最易被忽略的其实是空指针检查和长度控制——很多线上 crash 就源于把未初始化或已释放的 char* 直接喂给 std::string 构造函数,而开发者误以
