我需要一种快速访问容器中数据的方法。
所以我记得那个数据位置的迭代器。之后可能会修改容器(添加和删除元素),但如果我使用不会使我的迭代器无效的容器类型(如std::map
or std::list
)我很好。
另外我的数据可能不在容器中(还),所以我设置了一个迭代器container.end()
来反映这一点。
哪个标准容器保证end()
在添加和删除元素时不会改变?所以我仍然可以将我的迭代器与返回的值进行比较,container.end()
而不会得到假阴性。
我需要一种快速访问容器中数据的方法。
所以我记得那个数据位置的迭代器。之后可能会修改容器(添加和删除元素),但如果我使用不会使我的迭代器无效的容器类型(如std::map
or std::list
)我很好。
另外我的数据可能不在容器中(还),所以我设置了一个迭代器container.end()
来反映这一点。
哪个标准容器保证end()
在添加和删除元素时不会改变?所以我仍然可以将我的迭代器与返回的值进行比较,container.end()
而不会得到假阴性。
23.2.4/9 说关联容器:
insert 和 emplace 成员不应影响迭代器和对容器的引用的有效性,而擦除成员应仅使迭代器和对被擦除元素的引用无效
现在,有些地方标准谈到不使“迭代器和对容器元素的引用”无效,因此不包括end()
. 我不相信这是其中之一——我很确定end()
迭代器是“容器的迭代器”。
23.3.5.4/1 表示std::list
“insert
不影响迭代器和引用的有效性”,而 23.3.5.4/3 表示erase
“仅使迭代器和对已擦除元素的引用无效”。同样,end()
迭代器是迭代器,因此不排除它们的有效性。
需要注意的一件事是,对于任何容器,swap
都可以使 end() 迭代器无效(我认为这是因为有两种“自然”行为,即 end 迭代器指向同一个容器的末尾,或者指向末尾它被交换的一个,但标准不想规定或排除其他可能性)。但你不是在交换,只是添加和删除元素。
根据我的经验,迭代器从擦除或添加调整大小时会中断(这也适用于std::vector
' s 的存储)。并且不分配内存块:它们通常分配单个节点(并且大多数实现将桶作为项目的链接列表(例如,))。std::dequeue
std::string
std::list
std::map
std::unordered_map
std::list
如果您需要一个幸存的end()
迭代器,请选择一个std::list
(我这样做是为了我的 Signal/Slots 实现,为了他们的令牌)或使用std::vector
/进行您自己的个人簿记std::dequeue
。
编辑:因此,std::list
如果您的列表本身永远不会消失(它们不会),那么这是让您的迭代器始终有效的好方法。从另一个答案中,如果您需要标准的清晰度:
23.3.5.4/1 说 std::list 插入“不影响迭代器和引用的有效性”,而 23.3.5.4/3 说擦除“仅使迭代器和对被擦除元素的引用无效”。同样, end() 迭代器是迭代器,因此不排除它们的有效性。-另一个答案
代替迭代器,使用 avector
并存储索引值。他们将在任何重组中幸存下来。迭代器主要用于指定范围的成对使用;如您所见,挂在单个迭代器上会变得混乱。