我的代码中有一部分广泛使用字符串视图。在任何地方使用std::string
都是不可想象的,并且char const*
无法使用,因为存在关联的容器,许多比较以及用原始原始字符串很难完成的操作。
但是,有一个地方最终将处理C API,并且它需要以null结尾的字符串:
auto sv = std::string_view{/* ... */};
c_api(sv.data());
尽管这在我的情况下很好用,但我想确保一切正常,并断言字符串以null终止,因为我的系统在构造字符串视图并将其发送到该系统时将不使用子字符串视图,并且要么它们来自字符串文字或std::string
。我知道我会没事的。
然而,另一位程序员可能不知道所有这些,而是尝试在字符串视图上使用substr
,或发送非空终止的字符串。非空终止的字符串是不好的,因为它将导致未定义的行为,但是字符串视图中的子字符串甚至更糟,因为在发送到C API时不会应用上限,并且不会调用任何未定义的行为,但是会而是引入一个很难发现的具有意外行为的错误。
所以我想用一个断言来传达它:
auto sv = std::string_view{/* ... */};
assert(*(sv.data() + sv.length()) == '\0'); // Yay?
c_api(sv.data());
但是我发现它不完整且容易出错,因为它可能超出空终止字符串的界限。
是否可以安全地断言字符串视图确实以null终止?
这可能会很痛苦,但是我会写自己的string_view
,保证可以将其终止为null。
因为string_view
的构造可以像
char array[3] = {'B', 'a', 'r'};
std::string_view array_v(array, sizeof array);
测试
*(sv.data() + sv.length()) == '\0'
在这种情况下是未定义的行为,因为最后一个有效索引是2
,但是您访问了3
。 std::string_view
需要公开它不知道的信息,以便您执行此操作,并且由于它不知道,因此您无法可靠地知道。