Date: Mon, 8 Dec 2025 08:09:41 -0800
I'm not seeing the reason why this is something we need to change.
After that insertion: the references, iterators, and pointers that
were formed before the insertion no longer point/refer to the same
things they did before. The contents of the objects may have been
moved along. I'd probably be surprised that the end() iterator I
grabbed before is now "safe" to dereference.
Also, with sufficient magic, the end iterator in a vector could be
some sentinel value (I'm ignoring ranges for this discussion). And as
long as the implementation makes vector::iterator behave correctly
(recall, it doesn't have to be implemented as a raw pointer). So on
an implementation that uses raw pointers, then the end iterator
functionally becomes a pointer to the last element. But the
implementation that uses something different, that end iterator may
still be the end iterator. And an implementation could choose
differently between debug and release builds.
What's the use-case for this change to be useful?
On Mon, Dec 8, 2025 at 6:45 AM Nikl Kelbon via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> The standard needs to better clarify the section on vector iterator invalidation.
>
> Why i think its important:
>
> Some implementations added checks like: "oh, we must store all .end() iterators into global map under mutex and mark them invalid on each push_back, it will be SO useful for our developers!"
> So, minimal example where it breaks completely:
>
> std::vector<int> v;
> v.reserve(10);
>
> v.push_back(1);
>
> auto b = v.begin();
> auto e = v.end();
> v.push_back(1);
> ++b;
> REQUIRE(b == e); // assertion failure:
> // _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible");
>
>
> Its common pattern when using vector to reserve memory and push values, there are no "better way to do it", thats why it must be valid
>
>
> Now about standard:
>
> here's a quote from the standard regarding append_range and, apparently, push_back (https://eel.is/c++draft/vector#modifiers-2):
>
> If no reallocation happens, then references, pointers, and iterators before the insertion point remain valid but those at or after the insertion point, including the past-the-end iterator, are invalidated
>
> It explicitly states that despite there are no relocation happen, the past-the-end iterator is invalidated, although there's no reason for a vector to be so.
> Yes, a past-the-end iterator will no longer be past-the-end, but that doesn't make it invalid. In any implementation, even a foolish one, it's hard to imagine how, without relocation, this iterator could become anything other than just an iterator to the last element of the vector.
>
> I think in this case standard should separate invalidation and what happens here - its not invalidation rly.
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
After that insertion: the references, iterators, and pointers that
were formed before the insertion no longer point/refer to the same
things they did before. The contents of the objects may have been
moved along. I'd probably be surprised that the end() iterator I
grabbed before is now "safe" to dereference.
Also, with sufficient magic, the end iterator in a vector could be
some sentinel value (I'm ignoring ranges for this discussion). And as
long as the implementation makes vector::iterator behave correctly
(recall, it doesn't have to be implemented as a raw pointer). So on
an implementation that uses raw pointers, then the end iterator
functionally becomes a pointer to the last element. But the
implementation that uses something different, that end iterator may
still be the end iterator. And an implementation could choose
differently between debug and release builds.
What's the use-case for this change to be useful?
On Mon, Dec 8, 2025 at 6:45 AM Nikl Kelbon via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> The standard needs to better clarify the section on vector iterator invalidation.
>
> Why i think its important:
>
> Some implementations added checks like: "oh, we must store all .end() iterators into global map under mutex and mark them invalid on each push_back, it will be SO useful for our developers!"
> So, minimal example where it breaks completely:
>
> std::vector<int> v;
> v.reserve(10);
>
> v.push_back(1);
>
> auto b = v.begin();
> auto e = v.end();
> v.push_back(1);
> ++b;
> REQUIRE(b == e); // assertion failure:
> // _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible");
>
>
> Its common pattern when using vector to reserve memory and push values, there are no "better way to do it", thats why it must be valid
>
>
> Now about standard:
>
> here's a quote from the standard regarding append_range and, apparently, push_back (https://eel.is/c++draft/vector#modifiers-2):
>
> If no reallocation happens, then references, pointers, and iterators before the insertion point remain valid but those at or after the insertion point, including the past-the-end iterator, are invalidated
>
> It explicitly states that despite there are no relocation happen, the past-the-end iterator is invalidated, although there's no reason for a vector to be so.
> Yes, a past-the-end iterator will no longer be past-the-end, but that doesn't make it invalid. In any implementation, even a foolish one, it's hard to imagine how, without relocation, this iterator could become anything other than just an iterator to the last element of the vector.
>
> I think in this case standard should separate invalidation and what happens here - its not invalidation rly.
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-12-08 16:09:55
