Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtain iterator from pointer or reference

I would like to know if it is possible to obtain an iterator to an object inside a container (e.g. std::vector<...>) by only having access to the object inside the container, e.g. through a reference (which implies we have access to a pointer to it using the & operator). For example, normally we declare an iterator as

std::vector<int>::iterator = vec.begin();

or

std::vector<int>::iterator = next(vec.begin(), idx);

but in the first example we are most probably about to iterate through the container, in order, while in the second example we know the index of the object we require. I would like to know if we can obtain the iterator to an object without knowing at which index it resides in the container, but if we do have a reference or a pointer to it, as explained above.

It might appear that this question has already been asked here, but it seems more like the OP wanted others to fix his code, rather than answering the general question, so the answers are not so satisfactory in my opinion. Also, the answer here seems to say that we can initialize an iterator with a constructor, as shown below

std::vector<int>::iterator it(...);

but I have not been able to find any evidence of a constructor for the std::iterator class in the official documentation (and neither have I been able to find any documentation on std::vector<...>::iterator) so I am wary to use the constructor shown above, even if it compiles.

NOTE

I use std::vector as an example above, but ideally I would like this to work for any container, e.g. std::list or std::deque

like image 956
Konrad Avatar asked May 08 '16 15:05

Konrad


People also ask

Are iterators just pointers?

The most obvious form of an iterator is a pointer. A pointer can point to elements in an array and can iterate through them using the increment operator (++). But, all iterators do not have similar functionality as that of pointers.

Is iterator like pointer?

An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container. They can be visualised as something similar to a pointer pointing to some location and we can access content at that particular location using them.

Can you pass an iterator by reference?

You could pass a const reference, but usually iterators are small enough that it gives no advantage over passing by value.

Are iterators faster than pointers?

Iterators is a generic concept. They work on all sorts of containers and have similar interface. Accessing the array element directly like arr_int[i] is definitely faster because it directly translates to pointer arithmetic.


2 Answers

Specifically for std::vector (and other contiguous containers like std::string), given a pointer to an object in the vector p, we can simply do:

auto iter = v.begin() + std::distance(v.data(), p);

This is guaranteed by the contiguity contract. Note that random access is insufficient here, the above will not work for std::deque.

For any other container, there's no easy way of doing this. You'd have to just use find_if:

auto iter = std::find_if(c.begin(), c.end(), [p](auto const& o) { return &o == p; });

For intrusive containers, the iterator will be encoded into the object itself somehow so there will be some direct mechanism for converting p to an iterator. But that will be dependent on the intrusive container itself.

like image 190
Barry Avatar answered Sep 21 '22 12:09

Barry


You can use the find function---it returns an iterator---, supported on (almost?) all containers, to find your objects. If there are several objects which are equal under the operator==, iterate until the one with the same address has been found.

like image 36
blazs Avatar answered Sep 19 '22 12:09

blazs