C++ Logo


Advanced search

Re: On "transparently replaceable" in std::vector operations

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Fri, 30 Apr 2021 09:33:26 -0400
On Fri, Apr 30, 2021 at 7:37 AM Giuseppe D'Angelo via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> Hello,
> On 30/04/2021 01:56, Jason McKesson via Std-Discussion wrote:
> >
> > By inserting an object into a vector, you have conceptually changed
> > the address of all of the objects past that one in the container.
> > However, any pointers/references cannot themselves move to aim at the
> > correct object. Therefore, such pointers/references should no longer
> > be considered valid pointers/references to what they pointed
> > to/referenced.
> >
> > Put simply, a pointer/reference to an element in a container is not,
> > and should not be considered, a fancy index.
> I never said that pointers/references/iterators should magically move.
> In fact, I said that pointers would point to the element that ends up
> being in the position they were pointing to.

My point is that they *should* "move". A pointer to an element should
be a pointer to that element and no other element, unless you
explicitly modify that element. Because the nature of `vector` makes
that impossible implementation-wise, the only reasonable alternative
is to make them invalid.

> You're basically arguing that "it is what it is" regarding the lack of
> such a guarantee. That is, the mental model that `vector` to go with is
> a mental model that invalidates pointers, even if:
> * such invalidation is unenforceable (unlike iterators);
> * such invalidation doesn't actually happen in any implementation (are
> implementations allowed to have extra capacity on the left to optimize
> prepend? That makes a mess out of capacity(), but maybe there's an
> escape hatch/hat trick);
> * such invalidation cannot even happen because of (new? old?) language
> rules (unlike iterators, and due to a lack of an ad-hoc
> `std::invalidate` facility) and therefore it's not usable in
> optimizations, sanitizers, etc.;
> * it costs precisely zero for an implementation provide the extra
> guarantee (in fact, is it already "accidentally" offered today by all
> implementations?).
> I'm not sure if I'm 100% convinced. A `vector` isn't an arbitrary data
> structure, it's a quite specific one, with clear operational semantics.

But it is a container, and it should act like one. Pointers to
elements in a container should act like pointer to elements in every
other container, except for when that is made impossible by some
specific nature of a specific container. And in those cases, those
pointers should be invalidated; they shouldn't do something weird like
magically transform into pointers to other elements.

And I'd like to point out that there's not really any practical
benefit to creating a special rule like this for `vector`. That is, it
doesn't let you do anything you couldn't do with indices if you know
you're working with a `vector`. So you should just use indices to make
it clear to everyone reading your code that you expect the underlying
elements to shift around.

In any case, you wanted to understand the conceptual reasoning behind
it, and this is it. You don't have to agree with it, but this is the
logic behind it.

Received on 2021-04-30 08:33:40