C++ C++;:从值类型指针转换为包含迭代器

C++ C++;:从值类型指针转换为包含迭代器,c++,C++,std::unordered_-map提供了类似于find的方法,这些方法返回std::unordered_-map::iterator。据我所知,迭代器仍然有效,除非发生重新灰化 但我的怀疑是,对于往返::iterator->T*->::iterator,类似于Linux链表中的“hack”。我认为这是因为迭代器只需要通过->second进行去引用,但我不知道在容器中哪里需要持久的存储类型 那么,我说得对吗?我是否需要将迭代器保持在T*ptr=&myiterator->second之后,返回到

std::unordered_-map
提供了类似于
find
的方法,这些方法返回
std::unordered_-map::iterator
。据我所知,迭代器仍然有效,除非发生重新灰化

但我的怀疑是,对于往返
::iterator
->
T*
->
::iterator
,类似于Linux链表中的“hack”。我认为这是因为迭代器只需要通过
->second
进行去引用,但我不知道在容器中哪里需要持久的存储类型

那么,我说得对吗?我是否需要将迭代器保持在
T*ptr=&myiterator->second
之后,返回到迭代器指针,该迭代器指针的
->second
成员地址是
ptr

这个问题自然也适用于其他容器的迭代器。

关联容器(
多集
映射
多映射
,以及它们的
无序
兄弟)在向容器添加元素时不会使指针或引用无效;它们可以使迭代器失效。此外,删除元素时,只有迭代器、指针和对这些元素的引用无效。这样做的一个结果是,如果您获取一个元素的地址,只要该元素仍在容器中,该地址就仍然有效


没有可移植的方法可以直接将元素的地址转换为指向该元素的迭代器。如果需要这样做,您必须搜索元素。

第一个问题很简单:一般来说,没有直接的方法可以从指向元素的指针或值获取迭代器。也就是说,要从值中获取迭代器,通常需要搜索容器。由于
std::vector
必须是连续的,因此可以使用简单的计算从指针获取迭代器(这要求
v
为非空):

标准:向量v(…); T*ptr=。。。; std::vector::iterator(v.begin()+(ptr-&v[0]); 要跟踪迭代器和值是否保持稳定,这并不是很简单,因为相关的保证分布在多个子句上,例如:

  • 23.2.1[容器.要求.概述]第11段:

    除非另有规定(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不得使迭代器失效或更改容器内对象的值

  • 23.2.4[关联需求]第9段:

    插入和插入成员不得影响迭代器和对容器的引用的有效性,擦除成员应仅使迭代器和对已擦除元素的引用无效

  • 23.2.5[通知要求]第9段:

    。。。重新分级会使迭代器、元素之间的顺序更改以及元素出现在其中的bucket更改无效,但不会使元素的指针或引用无效

  • 23.2.5[通知要求]第14段:

    insert和emplace成员不应影响容器元素引用的有效性,但可能使容器的所有迭代器无效

  • 23.2.5[通知要求]第15段:

    如果(N+N)
  • 上述子句应该是关于关联容器的迭代器有效性的重要子句。无序关联容器中的迭代器有效性完全取决于容器是否被重新格式化。似乎可以控制再灰化以避免意外发生


    然而,无序容器的整体思想是使用
    find()
    定位对象非常有效。不必将迭代器存储到元素中,因为您可以找到它们。当然,如果你有一个
    std::unordered\u multimap
    或者一个
    std::unordered\u multiset
    你可能需要知道你在看哪个等价元素。

    你必须存储迭代器。不是每个迭代器都会产生T*@计算机:你的意思是,
    &myiterator->second
    不需要生成存储在容器中的实际值的地址?据我所知,当容器发生更改时,允许容器更新所有活动迭代器。因此,对
    &myiterator->second
    的两次求值可能会产生不同的指针。例如,std::vector迭代器的实际实现依赖于实现,传统上T*我还没有找到相应的标准部分,但表示迭代器在重新刷新时无效,而元素引用和指针(
    ValueT
    在我的操作说明中)保持有效。
    std::vector<T> v(...);
    T* ptr = ...;
    std::vector<T>::iterator it(v.begin() + (ptr - &v[0]));