存储std::string_view的容器元素是否一定指向以null结尾的字符串?
结论
你给出的示例代码可以安全运行,但这种用法不具备普适性,不建议推广到所有std::string_view使用场景。
具体说明
- 首先,C++标准没有要求
std::string_view指向的字符序列以null结尾。std::string_view的设计定位是轻量视图,仅存储起始指针和序列长度两个信息,和底层字符序列是否有末尾null完全无关,它的data()方法也不会自动补null。 - 示例代码的安全性来自初始化用的字符串字面量的特性:C++标准明确规定,
"abc"这类普通字符串字面量会隐式在末尾添加'\0',其实际类型为const char[N],N等于字面量可见字符数+1,最后一位就是补的null字符。用这类字面量初始化std::string_view时,data()返回的就是字面量本身的起始地址,因此末尾天然带null,传给printf("%s")不会出问题。 - 这种安全仅适用于你当前的特定场景,一旦
std::string_view的来源发生变化,就会触发未定义行为或者错误输出,典型的反例包括:// 手动指定长度构造,只取前3个字符,%s会输出后续多余内容 std::string_view sv1("abcdef", 3); // 从无末尾null的字符数组构造,会导致越界读 char arr[] = {'a', 'b', 'c'}; std::string_view sv2(arr, 3); // 从std::string的子片段构造,%s会输出超出子串长度的内容 std::string s = "abcdef"; std::string_view sv3 = s.substr(1, 3);
最佳实践
不要假设std::string_view的data()返回的是符合预期的null结尾C风格字符串,如果确实需要传给接收C字符串的接口,推荐显式构造临时std::string保证安全:
foo(std::string(elem).c_str());
如果对性能敏感,也可以为函数添加明确的前置条件注释,标注传入的std::string_view必须指向null结尾的完整序列。
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

