为什么在 C++11 之后 std::basic_string 的尾后迭代器的取消引用仍然是 UB?

问题描述 投票:0回答:1

众所周知,C++11 为 std::basic_string 添加了一个 null 终止符(这不计入大多数成员函数)。但是当我阅读 cpp ref 时,我发现对 end() 的取消引用是一个 UB(这一段与 std::vector 的段落几乎相同)。为什么会出现这种情况? 或者这是 cpp ref 的错误(请提供文档以供验证)?

我尝试过 GNU C++,但不幸的是 __gnu_debug 似乎不包含 std::string 迭代器的检查器。 Clang++ 的消毒剂也没有。

c++ iterator c++17 undefined-behavior stdstring
1个回答
0
投票

正确;即使

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++ 样式迭代器时的错误。

© www.soinside.com 2019 - 2024. All rights reserved.