string_view与string拼接的正确安全高效方式及data()风险解析
拼接std::string_view与std::string的正确方式
直接尝试std::string_view与std::string相加会触发编译错误,因为C++标准库并未提供这两种类型的operator+重载:
std::string_view foo{"foo"}; auto concat = foo + std::to_string(45); // 编译错误
错误信息如下:
no match for ‘operator+’ (operand types are ‘std::string_view’ {aka ‘std::basic_string_view’} and ‘std::string’ {aka ‘std::__cxx11::basic_string’}) 18 | auto concat = foo + std::to_string(45); | ~~~ ^ ~~~~~~~~~~~~~~~~~~ | | | | | std::string {aka std::__cxx11::basic_string<char>} | std::string_view {aka std::basic_string_view<char>}
下面分析两种可行写法的安全性与正确性:
1. 错误且不安全的写法:使用data()拼接
auto concat = foo.data() + std::to_string(45);
这种写法看似能运行,但存在严重的安全隐患:
std::string_view::data()返回的缓冲区不保证以空字符'\0'结尾。比如当string_view是从std::string的子串生成时(如std::string s = "abcde"; std::string_view sv = s.substr(1,3);),sv.data()指向的是"bcd",但后续没有'\0'。此时将其当作C风格字符串与std::string相加,会读取到内存中的垃圾数据,触发未定义行为。- 即使当前string_view的来源是带'\0'的字符串,这种写法也不具备鲁棒性——后续只要string_view的来源变为子串或非空终止的缓冲区,代码就会崩溃或产生错误结果。
2. 正确、安全且高效的写法:构造std::string后拼接
auto concat = std::string(foo) + std::to_string(45);
这种写法的优势在于:
- 安全性:构造
std::string时会完整复制string_view指向的所有字符,确保新字符串内容完整且以'\0'结尾,不会出现越界读取的问题。 - 正确性:调用
std::string的operator+重载进行拼接,行为完全符合标准,不存在未定义行为。 - 效率:现代编译器会对临时对象的构造进行优化,且复制string_view内容是生成新字符串的必要开销,不存在额外的性能浪费。
总结:拼接std::string_view与std::string时,必须通过构造std::string的方式实现,绝对不能使用data()的写法。
内容的提问来源于stack exchange,提问作者rookie
相关产品推荐
相关产品推荐

