从指针或引用中获取迭代器

2022-01-10 00:00:00 pointers containers iterator c++

我想知道是否可以通过仅访问容器内的对象来获取容器内对象的迭代器(例如 std::vector<...>)容器,例如通过引用(这意味着我们可以使用 & 运算符访问指向它的指针).例如,通常我们将迭代器声明为

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();

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.

似乎已经在这里提出了这个问题,但看起来更像OP希望其他人修复他的代码,而不是回答一般问题,所以我认为答案并不那么令人满意.另外,here的答案似乎是说我们可以用构造函数初始化迭代器,如下图

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(...);

但我无法在官方文档中找到 std::iterator 类的构造函数的任何证据(我也无法在 std::vector 上找到任何文档<...>::iterator) 所以我很谨慎地使用上面显示的构造函数,即使它可以编译.

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.

注意

我使用 std::vector 作为上面的示例,但理想情况下我希望它适用于任何容器,例如std::liststd::deque

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

推荐答案

专门针对 std::vector(以及其他连续容器,如 std::string),给定一个指向向量 p 中的对象的指针,我们可以简单地这样做:

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);

这是由邻接合同保证的.注意这里随机访问是不够的,上面的对std::deque 不起作用.

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

对于任何其他容器,都没有简单的方法可以做到这一点.你只需要使用 find_if:

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; });


对于 intrusive 容器,迭代器将以某种方式被编码到对象本身中,因此将有一些直接的机制将 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.

相关文章