C++ 给定一个指向列表元素的指针,您能找到该元素的迭代器吗?

C++ 给定一个指向列表元素的指针,您能找到该元素的迭代器吗?,c++,list,iterator,C++,List,Iterator,这个问题可能是不言自明的,但是如果我有一个std::list对象,那么在给定一个指向元素的T*值的情况下,是否有任何标准方法来获取元素的迭代器 如果T是一个用户定义的类型,那么似乎取消引用指针并使用find\u If可以完成这项工作,但对我来说这似乎效率低下。如果您试图通过值在容器中查找一个元素,那么您需要在容器中迭代,直到找到某个元素。但是如果你有一个指针,直觉上会觉得应该有一个更直接的方法。我的基本理解使我认为列表项的迭代器和它的指针之间应该存在某种1对1的关系,因为列表在STL中是双重链接

这个问题可能是不言自明的,但是如果我有一个
std::list
对象,那么在给定一个指向元素的
T*
值的情况下,是否有任何标准方法来获取元素的迭代器

如果
T
是一个用户定义的类型,那么似乎取消引用指针并使用
find\u If
可以完成这项工作,但对我来说这似乎效率低下。如果您试图通过值在容器中查找一个元素,那么您需要在容器中迭代,直到找到某个元素。但是如果你有一个指针,直觉上会觉得应该有一个更直接的方法。我的基本理解使我认为列表项的迭代器和它的指针之间应该存在某种1对1的关系,因为列表在STL中是双重链接的,但我真的没有太多的支持

<>我对C++迭代器不太熟悉,所以如果有人能解释为什么有或没有办法这样做,那将是有益的。
编辑:Potatoswatter提供了一个很好的C++11解决方案,但我仍然对是否有与C++03兼容的解决方案感兴趣。

您必须在类中定义/实现迭代器。如果我不想实现迭代器,我通常使用指针。

没有标准算法可以在满足条件的范围内找到迭代器
find
使用元素的值,但这根本不是一回事<代码>如果使用比较地址的lambda查找\u将起作用

编写通用版本很容易:

template< typename iter, typename t >
iter iterator_from_ptr( iter first, iter last, t * ptr ) {
    while ( first != last ) {
        // For C++03 compatibility, use &* first instead of addressof.
        if ( std::addressof( * first ) == ptr ) return first;
        ++ first;
    }
    return last;
}
模板
国际热核实验堆迭代器(国际热核实验堆第一,国际热核实验堆最后,t*ptr){
while(第一个!=最后一个){
//为了与C++03兼容,请先使用&*而不是addressof。
如果(std::addressof(*first)==ptr)首先返回;
++第一,;
}
最后返回;
}
用法:
iterator\u from\u ptr(my\u list.begin(),my\u list.end(),ptr)

正如你提到的,它是低效的,具体来说是O(N)。加快速度违反了C++的规则:您有一个指向对象的指针,该对象是
std::list
节点的成员,而
list::iterator
实际上是指向
std::list
节点的指针。但(通常)无法从指向成员的指针转到指向整个对象的指针。(更不用说迭代器抽象了。)

中的
std::find()
是否适合您?如果值类型已实现
运算符==
,则它应该可以工作

#include <algorithm>
auto it = std::find(list.begin(), list.end(), *ptr);
#包括
auto it=std::find(list.begin(),list.end(),*ptr);

虽然我不推荐下面的功能,但此功能可以满足您的要求。它依赖于列表实现的知识,所以它实际上只是一个有趣的练习,不应该在生产代码中依赖:)

模板
类型名列表::迭代器迭代器fromptr(T*a)
{
自动偏移=偏移量(\u列表\u节点,\u M\u数据);
void*ptr=(void*)a;
ptr-=偏移量;
返回_List_迭代器(static_cast(ptr));
}

编辑:使用gcc-4.8.2进行测试。

我不明白这个问题-您是在询问如何在列表中找到一个元素,给定一个指向要找到的元素的指针吗?
std::list
保留
t
类型的对象。给定一个
std::list::iterator
,您可以获取对象的引用,您可以使用该引用获取对象的地址。但是,指针不知道它指向的对象在
std::list
中的位置。这是
std::list
。它不是OP的类,并且已经实现了迭代器。指针也不能作为双链表的迭代器。我认为他不希望这样。列表中可能有多个项目等于
*ptr
。他不想要第一个匹配
*ptr
的。他希望迭代器指向地址为
ptr
的项。这一点后来在另一个答案中的注释中才变得清楚:-(
std::addressof
不在
C++03
中。我认为这是值得一提的。感谢您的回复Potatostater。我在原始问题中没有提到这一点,但是
std::list
没有很多元素,但是
t
非常大,因此进行值比较可能会变得复杂而且可能会很慢。
O(N)
仍然有点令人不快,但对于我的特殊问题,它肯定足够好了。@Matt如答案中所述,只需先使用
&*first
。只要
T
不会使一元
操作符过载&
(颤抖),您就可以了。
template <typename T>
typename list<T>::iterator iteratorFromPtr(T* a)
{
 auto offset = offsetof(_List_node<T>, _M_data);
 void* ptr = (void*)a;
 ptr -= offset;
 return _List_iterator<T>(static_cast<_List_node<T>*>(ptr));
}