Let's say I have an std::vector<int> arr
of 5 elements { 1, 2, 3, 4, 5 }
.
Is it safe to get a subrange from it like sub = std::span{ arr.begin() + 2, arr.end() }
and dereference element at -1
like *(sub.begin() - 1)
?
In terms of pointers this looks safe, but what about iterators?
If this is safe for vector
and span
, what about list
?
Let's say I have an std::vector<int> arr
of 5 elements { 1, 2, 3, 4, 5 }
.
Is it safe to get a subrange from it like sub = std::span{ arr.begin() + 2, arr.end() }
and dereference element at -1
like *(sub.begin() - 1)
?
In terms of pointers this looks safe, but what about iterators?
If this is safe for vector
and span
, what about list
?
2 Answers
Reset to default 1From the definition of LegacyBidirectionalIterator
:
The begin iterator is not decrementable and the behavior is undefined if --container.begin() is evaluated.
And it - n
is defined in terms of --
, so no, this is not safe.
In terms of pointers this looks safe, but what about iterators?
This is unsafe, and it is reasonable to assume that library implementations will verify offsets to avoid them, e.g. MSV-STL when _ITERATOR_DEBUG_LEVEL
is enabled.
In this case, ranges::subrange
may meet your needs as long as the operation on the original iterator is safe, since it returns the original iterator-pair.
However, subscripting on a ranges::subrange
may still be unsafe because its operator[]
may still be aware of out-of-bounds:
auto sub = std::ranges::subrange{ v.begin() + 2, v.end() };
auto x = sub.begin()[-1]; // safe
auto y = sub[-1]; // unsafe, UB
So, in any case, even if you think it is safe, it is better not to try to access out-of-bounds elements to avoid potential undefined behavior.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1743747764a4500326.html
auto& two = *std::prev(std::addressof(*sub.begin()));
would be safe though – Ted Lyngmo Commented 9 hours ago