std::string_view 能避免拷贝因其仅存储 const char* 指针和 size_t 长度,不拥有数据、不分配内存,仅为已有字符串的只读切片;需确保底层存储生命周期长于其自身。
std::string_view 为什么能避免拷贝
因为 std::string_view 只存两个字段:const char* 指针和 size_t 长度,不拥有数据,也不分配内存。它只是对已有字符串内存的“只读切片”。只要原始字符串生命周期长于 string_view 实例,就不会出问题。
常见误用是把它绑定到临时 std::string 的 c_str() 或直接传入字面量后立即析构:
std::string_view bad() {
return std::string("hello").c_str(); // 悬空指针!
}
正确做法是确保底层存储稳定:
- 绑定全局/静态字符串字面量(
"hello"类型是const char[6],寿命无限) - 绑定已存在的
std::string对象的data()和size() - 作为函数参数接收,由调用方保证实参生命周期足够长
函数参数中用 string_view 替代 const std::string& 的时机
当函数只读取内容、不依赖 std::string 的成员函数(如 find、substr 等),且你希望兼容 C 风格字符串、字面量、std::string、std::array 等多种来源时,std::string_view 是更优选择。
立即学习“C++免费学习笔记(深入)”;
例如:
void log_message(std::string_view msg) { /* 只打印或解析 */ }
log_message("error"); // OK,无需构造 string
log_message(std::string("timeout")); // OK,隐式转换
log_message(some_string); // OK
但注意:如果函数内部需要调用 msg.find("://"),没问题;但若需要 msg.append(".log"),就不能用 string_view —— 它没有可变接口。
性能差异在高频调用场景(如解析循环、日志批量写入)中明显:省去每次构造 std::string 的堆分配和 memcpy。