是否保证 std::string_view 文字以空值结尾?

Posted

技术标签:

【中文标题】是否保证 std::string_view 文字以空值结尾?【英文标题】:Is a std::string_view literal guaranteed to be null-terminated? 【发布时间】:2019-07-29 09:02:53 【问题描述】:

我知道琐碎的std::string_view 不能保证以空值结尾。但是,我不知道 std::string_view 文字是否保证以空值结尾。

例如:

#include <string_view>

using namespace std::literals;

int main()

    auto my_sv = "hello"sv;

C++17 或更高版本是否保证my_sv.data() 以空值结尾?

=== 下面更新===

以下均来自n4820:

    根据 5.13.5.14,字符串文字以空值结尾。 根据 5.13.8,用户定义的字符串文字由字符串文字加上自定义后缀组成。比如说,"hello"svhello 是字符串文字,sv 是后缀。 根据 5.13.8.5,"hello"sv 被视为operator "" sv(str, len); 形式的调用,根据 5.13.5.14,str 是 空终止。 根据 21.4.2.1,svdata() 必须返回 str

他们能否证明 "hello"sv.data() 被 C++ 标准保证为空终止?

【问题讨论】:

在此站点上,使用答案上的绿色复选标记表示“已解决”;没有这样的复选标记表示“未解决”。您不应该在标题中写“已解决”等 string_view 是一个类。类不是以空值结尾的。准确解释您要问的问题会改善问题(也许提供一个代码示例来演示您所询问的案例的 string_view 用法) @M.M OP 在问什么不是很清楚吗?你认为像those 这样添加几行代码会有好处吗? @M.M sv[sv.size()] 是 UB,sv.data()[sv.size()] 不一定是 UB——但应该会引起紧张。我也不清楚 OP 询问的是哪一个。 @M.M 所以这个问题可以改写成类似“给定auto my_sv = "hello"sv;,C++17 或更高版本是否保证my_sv.data() 是空终止的?” 【参考方案1】:

所以让我们把简单的部分排除在外。没有string_view 曾经是“NUL 终止的”,因为该对象表示一定大小的字符范围。即使您从 NUL 终止的字符序列创建 string_viewstring_view 本身 仍然不是“NUL 终止”。

您真正要问的问题是:实现是否有一些余地来使声明 "some literal"sv 产生 string_viewdata 成员指向 NUL-由"some literal" 表示的终止字符串文字?也就是说,是这样的吗:

string_view s = "some literal"sv;

允许以任何方式与此不同:

const char *lit = "some literal";
string_view s(lit, <number of chars in of lit>);

在后一种情况下,s.data() 保证是指向字符串文字的指针,因此您可以将该指针视为指向以 NUL 结尾的字符串的指针。你问的是前者是否同样有效。

让我们调查一下。 definition for the operator""sv overloads are stated to be:

constexpr string_view operator""sv(const char* str, size_t len) noexcept;

返回:string_­viewstr, len

这是该函数行为的标准规范:它返回一个string_view,它指向str 提供的内存。因此,实现无法分配一些隐藏内存并使用它或其他任何东西;返回的string_view::data 需要返回与str相同的指针。

现在,这给我们带来了一个不同的问题:str 需要 是一个以 NUL 结尾的字符串吗?也就是说,编译器看到您正在使用 sv UDL 实现并因此从它将为作为 str 传递的字符串文字创建的数组中删除 NUL 字符是否合法?

我们来看看how UDLs for strings work:

如果L 是用户定义的字符串文字,则令str不带ud 后缀的文字,令len 为@987654346 中的代码单元数@(即,它的长度不包括终止空字符)。文字 L 被视为表单的调用

operator "" X(str, len)

注意我强调的短语。我们知道“没有 ud 后缀的文字”的行为。第二个短语特别提到了str 的预期 NUL 终止符。我想说这是一个非常明确的声明,str 将被赋予一个文字字符串。并且该文字字符串将按照 C++ 中的常规字符串文字规则构建,因此将以 NUL 结尾。

鉴于上述情况,我认为可以肯定地说,这里的实施没有回旋余地。 UDL 返回的string_view 必须 指向由 UDL 中指定的字符串字面量定义的数组,并且与任何其他字符串字面量一样,该数组 为 NUL-终止。

话虽如此,复习我的第一段。您不应该编写任何假定 string_view 是 NUL 终止的代码。即使string_view 的创建者和消费者是相邻的,我也会称其为代码异味。

【讨论】:

以上是关于是否保证 std::string_view 文字以空值结尾?的主要内容,如果未能解决你的问题,请参考以下文章

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

文件到 std::string_view

使用 std::string_view 的子字符串控制台输出 [关闭]

将函数参数 `const char*` 转换为 `std::string_view` 是不是安全?

用于 STL 容器的 std::string_view