17

我知道琐碎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

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

他们能证明"hello"sv.data()C++ 标准保证它是空终止的吗?

4

1 回答 1

20

所以让我们把简单的部分排除在外。Nostring_view永远是“NUL 终止的”,因为该对象表示一定大小的字符范围。即使您string_view从以 NUL 结尾的字符序列创建一个,它string_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 结尾的字符串的指针。你问的是前者是否同样有效。

让我们调查一下。重载定义为operator""sv

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

回报:string_­view{str, len}

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

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

让我们看看字符串的 UDL 是如何工作的

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

operator "" X(str, len)

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

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

话虽如此,查看我的第一段。您不应该编写任何假定 astring_view是 NUL 终止的代码。即使string_viewand 是消费者的创建者彼此相邻,我也会称其为代码气味。

于 2019-07-29T15:58:41.933 回答