About SSO: implementations normally use the size of the string to determine if the sequence of chars is held within the string's buffer, so removing a char can potentially require the sequence of chars to be moved from the allocated memory.

Julien V.


On December 12, 2023 4:44:19 a.m. EST, "Daniel Krügler via Std-Discussion" <std-discussion@lists.isocpp.org> wrote:
Am Di., 12. Dez. 2023 um 09:11 Uhr schrieb Yongwei Wu <wuyongwei@gmail.com>:

On Tue, 12 Dec 2023 at 14:14, Daniel Krügler <daniel.kruegler@gmail.com> wrote:

Am Di., 12. Dez. 2023 um 05:42 Uhr schrieb Yongwei Wu via
Std-Discussion <std-discussion@lists.isocpp.org>:

In the case of erase in the following form:

constexpr iterator erase(const_iterator);

basic_string does not say anything about iterator and reference
invalidation, while vector specifically says erase "invalidates
iterators and references at or after the point of the erase".

That's not quite right. We have [string.require] p4, which says:

4 References, pointers, and iterators referring to the elements of a
basic_string sequence may be invalidated
by the following uses of that basic_string object:
(4.1) — Passing as an argument to any standard library function taking
a reference to non-const basic_string
as an argument.
(4.2) — Calling non-const member functions, except operator[], at,
data, front, back, begin, rbegin, end,
and rend.

So, bullet (4.2) applies for erase, which is a non-const member
function that is not excluded by the listed functions.

Thank you.

I would argue this is quite weak and vague. vector::erase specifically
says it "invalidates iterators and references at or after the point of
the erase". That implies iterators pointing to elements before the
point of erase remain valid. That would be stronger than the point you
mention here. It does not make sense to me that string provides a
weaker guarantee than vector.

And the main part of the questions is why (under what circumstance).
Why should an iterator pointing to the point of erase be invalidated
for the contiguous sequence containers? The memory layout is fixed,
after all.

The reason, why the string wording is still that vague in
[string.require] is due to history, since in pre-C++11 a valid string
implementation could use reference-counting.

A reference-counting based implementation is no longer valid, but now
we have to acknowledge the possibility of short-string-optimization is
a special case for basic_string which does not apply to std::vector,
so we cannot expect that all that wording about
iterator/reference/pointer invalidation would be *exactly* the same. I
expect that a paper would be well-come that attempts to cleanup the
historical wording used in basic_string about when invalidation may
happen.

- Daniel