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

C++: cast from value type pointer to containing iterator

本文关键字:转换 包含 迭代器 指针 类型 C++      更新时间:2023-10-16

std::unordered_map<K,T>提供了类似find的方法,这些方法返回std::unordered_map<K,T>::iterator。据我所知,迭代器仍然有效,除非发生重新散列。

但我的怀疑是,没有保证::iterator->T *->::iterator的往返方式,类似于Linux链表中的"破解"。我认为这是因为迭代器只需要通过->second来取消引用,但我看不出在容器中需要持久存储类型。

那么,我说得对吗?我是否需要保留迭代器,或者T *ptr = &myiterator->second稍后是否可以返回到->second成员地址为ptr的迭代器指针?

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

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

std::vector<T> v(...);
T* ptr = ...;
std::vector<T>::iterator it(v.begin() + (ptr - &v[0]));

跟踪迭代器和值是否保持稳定并非易事,因为相关的保证分布在多个子句上,例如:

  1. 23.2.1【集装箱要求概述】第11段:

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

  2. 23.2.4[相关要求]第9段:

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

  3. 23.2.5[要求]第9段:

    Rehashing会使迭代器失效,更改元素之间的顺序,以及更改元素出现在哪个bucket中,但不会使指向元素的指针或引用失效。。。

  4. 23.2.5[要求]第14段:

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

  5. 23.2.5[要求]第15段:

    如果(N+N)<z*B,其中N是插入操作之前容器中元素的数量,N是插入的元素数量,B是容器的桶数,z是容器的最大负载因子。

以上子句应该是关于关联容器的迭代器有效性的重要子句。无序关联容器中的迭代器有效性完全取决于容器是否被重新散列。看来重洗是可以控制的,以避免意外发生。

然而,无序容器的整体思想是,使用find()定位对象是非常有效的。应该永远不需要将迭代器存储到元素中,因为您可以找到它们。当然,如果你有一个std::unordered_multimap<K, V>std::unordered_multiset<V>,你可能需要知道你在看哪个等效元素

关联容器(setmulti_setmapmulti_map及其unordered_同类)在向容器添加元素时不会使指针或引用失效;它们可以使迭代器无效。此外,删除元素时,只有迭代器、指针和对这些元素的引用无效。这样做的一个后果是,如果您获取一个元素的地址,那么只要该元素保留在容器中,该地址就会保持有效。

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