Date: Mon, 8 Dec 2025 09:24:58 -0600
Hello,
> minimal example where it breaks completely
This isn’t an example of anything breaking. This is UB, you’re relying on
something you should never rely on.
> there are no "better way to do it", thats why it must be valid
Reserving and pushing values is fine and common. You do not have to store
an end iterator and attempt to rely on fickle assumptions about the
underlying implementation though.
> iterator could become anything other than just an iterator to the last
element of the vector
The standard could say that end iterators become iterators to items if no
resize occurs on a push, that would be fine for most implementations, but I
don’t think this is very useful. It adds complexity and implementation
constraints and only facilitates a rather bug-prone practice with storing
iterators around vector mutation.
> *rly*
Pls tk th tme t wrt t wrds cmpltly.
Cheers,
Jeremy
On Mon, Dec 8, 2025 at 08:45 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
>
> minimal example where it breaks completely
This isn’t an example of anything breaking. This is UB, you’re relying on
something you should never rely on.
> there are no "better way to do it", thats why it must be valid
Reserving and pushing values is fine and common. You do not have to store
an end iterator and attempt to rely on fickle assumptions about the
underlying implementation though.
> iterator could become anything other than just an iterator to the last
element of the vector
The standard could say that end iterators become iterators to items if no
resize occurs on a push, that would be fine for most implementations, but I
don’t think this is very useful. It adds complexity and implementation
constraints and only facilitates a rather bug-prone practice with storing
iterators around vector mutation.
> *rly*
Pls tk th tme t wrt t wrds cmpltly.
Cheers,
Jeremy
On Mon, Dec 8, 2025 at 08:45 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 15:25:14
