C++ Logo

std-discussion

Advanced search

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

From: Hyman Rosen <hyrosen_at_[hidden]>
Date: Tue, 27 Apr 2021 21:00:37 -0400
Vector represents a set of elements held in contiguous storage, and
pointers to those elements are pointers to positions in that storage.
Vector isn't some mysterious data structure that holds its objects in
inscrutable ways. After moving data around in the storage, the pointers
still point to the same spots. If the programmer finds that useful, there's
no reason to have them be invalid for some abstract reason.

On Tue, Apr 27, 2021, 8:03 PM Jason McKesson via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> On Tue, Apr 27, 2021 at 11:02 AM Giuseppe D'Angelo via Std-Discussion
> <std-discussion_at_[hidden]> wrote:
> >
> > Hi,
> >
> > Suppose I have a `std::vector<X>` with sufficient extra capacity to
> > insert new elements without reallocation.
> >
> > [vector.modifiers] says that inserting an element at position `p`
> > invalidates all iterators, references and pointers from position `p`
> > onwards.
> >
> > I'm wondering why there's such a requirement for pointers (and
> > references), considering the paragraph about "transparently replaceable"
> > objects in [basic.life]:
> >
> > > http://eel.is/c++draft/basic.life#8
> >
> >
> > Couldn't that paragraph be used to guarantee that, in fact, pointers and
> > references after a non-reallocating insertion are still valid, but they
> > just refer to "other" objects in the vector -- depending on the their
> > position? For instance, in:
> >
> > > X* ptr = v.data();
> > >
> > > v.insert(v.begin(), x);
> > >
> > > use(*ptr); // <--
> >
> > could the last line be perfectly valid (not even a launder() required),
> > pointing to the newly inserted element?
> >
> > Of course the discussion can be generalized to erasure.
>
> Let's sidestep the whole issue of object models and just think of it
> from the perspective of a user. As far as I'm concerned, even if the
> object model made it OK, it would still be a terrible idea.
>
> A container contains a bunch of things. If you get a pointer to one of
> those things, then perform some operation on the container, what does
> your pointer point to?
>
> Logically, if you have a pointer to a thing in the container, if that
> thing is still in the container, your pointer should *still point to
> it*, right? That would make sense, yes? You have a pointer to some
> element, you inserted another element, and your pointer still points
> to the element it pointed to.
>
> From the perspective of the average user, a pointer or reference is
> not a fancy index into the container. It points at/references
> something that is in the container. And that pointer/reference means
> something to the user.
>
> After all, if they meant "the third element", then they could just
> keep an index instead of a pointer/reference, right?
>
> So from this point of view, if you perform an operation on a container
> that does not directly manipulate that element, there are only two
> reasonable possible states of that pointer/reference: either it still
> points at what it used to point at, or it is not valid.
>
> If you want the behavior of an index, then just *get an index*. Then
> it's clear to everyone what is actually going on. We shouldn't make
> pointers/references into `vector` behave like indices. And code that
> expects them to do so seems rather confused as to what it is actually
> trying to do.
>
> Plus, it's a lot less fragile to use an index when that's the behavior
> you want. After all, the pointer/reference validity can only be
> allowed if reallocation doesn't occur. Which is not (yet) a thing you
> can guarantee. It's better to write code that can't accidentally be
> broken.
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>

Received on 2021-04-27 20:00:53