我在实际的生产代码中发现了以下内容。
我怀疑它实际上有未定义的行为,但是,我在 cppreference 上找不到相关信息。您能否确认这是 UB 或有效代码,以及为什么这是 UB/valid(最好是引用标准)?
#include <vector>
int main(int, char **)
{
auto v = std::vector<int>({1,2,3,4,5});
auto begin = v.begin();
auto outOfRange = begin + 10;
auto end = v.end();
auto clamped = std::min(outOfRange, end);
return (clamped == end) ? 0 : 42;
}
Code on Compiler Explorer如您所见
begin + 10
将创建一个超出 std::vector
范围的迭代器.但是,该迭代器并未被使用,因为它使用
std::min
进行了限制。 .
最佳答案
operator+(n)
的操作语义,对于随机访问迭代器是这个 [random.access.iterators], Table 99 *:
difference_type m = n; if (m >= 0) while (m--) ++r; else while (m++) --r; return r;
而对于
++r
前提是[input.iterators], Table 95 *:Preconditions:
r
is dereferenceable.
与
begin() + n
从 m
的某个值开始,将不满足此前提条件如果 n
大于容器的大小。后 begin + 10;
你已经有了 UB,其余的代码是无关紧要的。GCC 标准库 sanitizer(用
-D_GLIBCXX_DEBUG
编译)会给你以下错误:/usr/include/c++/10/debug/safe_iterator.h:885:
In function:
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*,
std::__cxx1998::vector<int, std::allocator<int> > >,
std::__debug::vector<int>, std::random_access_iterator_tag>::_Self
__gnu_debug::operator+(const _Self&,
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*,
std::__cxx1998::vector<int, std::allocator<int> > >,
std::__debug::vector<int>,
std::random_access_iterator_tag>::difference_type)
Error: attempt to advance a dereferenceable (start-of-sequence) iterator 10
steps, which falls outside its valid range.
Objects involved in the operation:
iterator @ 0x0x7fffffffb900 {
type = __gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, std::allocator<int> > > (mutable iterator);
state = dereferenceable (start-of-sequence);
references sequence with type 'std::__debug::vector<int, std::allocator<int> >' @ 0x0x7fffffffb8c0
}
关于c++ - 对迭代器的钳制是否有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62710870/