众所周知,C++11 为 std::basic_string 添加了一个 null 终止符(这不计入大多数成员函数)。但是当我阅读 cpp ref 时,我发现对 end() 的取消引用是一个 UB(这一段与 std::vector 的段落几乎相同)。为什么会出现这种情况? 或者这是 cpp ref 的错误(请提供文档以供验证)?
我尝试过 GNU C++,但不幸的是 __gnu_debug 似乎不包含 std::string 迭代器的检查器。 Clang++ 的消毒剂也没有。
正确;即使
end()
是一个闭范围,[data(), data() + size()]
迭代器也无法间接访问。
据我所知,在调试模式下强制执行此操作的唯一主要编译器是 Microsoft Visual Studio:
#include <string>
int main(int argc, char* argv[]) {
return *std::string(argv[argc - 1]).end();
}
上述程序编译为
cl.exe a.cpp /EHsc /Zi /MDd /std:c++20 /D_ITERATOR_DEBUG_LEVEL=2
给出以下调试断言:
表达式:无法取消引用字符串迭代器,因为它超出范围(例如结束迭代器)
这样做的原因是,提供 null 终止符是为了方便需要 null 终止字符串的 C 风格 API;但这些是通过原始字符指针而不是迭代器访问字符串。因此,使尾后迭代器可解引用对此类代码没有任何帮助,并且可能隐藏使用 C++ 样式迭代器时的错误。