【发布时间】:2012-07-14 11:17:22
【问题描述】:
我在 std::vector 中有一组元素,这些元素从第一个元素开始按降序排序。我必须使用向量,因为我需要将元素放在连续的内存块中。而且我有一个集合,其中包含许多具有所描述特征的向量实例(始终按降序排序)。
现在,有时,当我发现较大集合(包含这些向量的集合)中有太多元素时,我会以类似于以下伪代码的方式丢弃这些向量中的最小元素:
grand_collection: collection that holds these vectors
T: type argument of my vector
C: the type that is a member of T, that participates in the < comparison (this is what sorts data before they hit any of the vectors).
std::map<C, std::pair<T::const_reverse_iterator, std::vector<T>&>> what_to_delete;
iterate(it = grand_collection.begin() -> grand_collection.end())
{
iterate(vect_rit = it->rbegin() -> it->rend())
{
// ...
what_to_delete <- (vect_rit->C, pair(vect_rit, *it))
if (what_to_delete.size() > threshold)
what_to_delete.erase(what_to_delete.begin());
// ...
}
}
现在,在运行此代码后,在what_to_delete 中,我有一组迭代器指向我想从这些向量中删除的原始向量(整体最小值)。请记住,原始向量在遇到此代码之前已排序,这意味着对于任何what_to_delete[0 - n],位置n - m 上的迭代器都不会指向比n 更远离同一向量开头的元素,其中m > 0。
从原始向量中擦除元素时,我必须将 reverse_iterator 转换为迭代器。为此,我依赖 C++11 的 §24.4.1/1:
reverse_iterator和iterator的关系是 &*(reverse_iterator(i)) == &*(i-1)
这意味着要删除vect_rit,我使用:
vector.erase(--vect_rit.base());
现在,根据 C++11 标准§23.3.6.5/3:
迭代器擦除(常量迭代器位置);效果:无效 在擦除点或之后的迭代器和引用。
这如何与 reverse_iterators 一起工作? reverse_iterators 内部是否通过引用向量的真实开始 (vector[0]) 来实现,并将该 vect_rit 转换为经典迭代器,以便擦除是安全的?还是 reverse_iterator 使用 rbegin()(即vector[vector.size()])作为参考点,删除任何远离向量 0-index 的内容仍然会使我的反向迭代器无效?
编辑:
看起来 reverse_iterator 使用 rbegin() 作为其参考点。以我描述的方式擦除元素在删除第一个元素后给了我关于不可引用迭代器的错误。而在插入到what_to_delete 时存储经典迭代器(转换为const_iterator)时工作正常。
现在,为了将来参考,标准是否指定了在随机访问 reverse_iterator 的情况下应将什么视为参考点?或者这是一个实现细节?
谢谢!
【问题讨论】:
-
问题是关于标准的字母,还是关于常见的实现?
-
据我了解,您没有/不想在这里使用
reverse_iterator。std::vector具有随机访问迭代器,这意味着您可以使用从.end()开始的常规iterator并将其向后移动。这样一来,您就不必做太多的魔法来使用.erase()。 -
我不相信
reverse_iterator甚至没有您所说的“参考点”。它只是一个普通的双向/随机访问迭代器的便利包装器;特别是,reverse_iterator的失效语义是“当且仅当包装的Iterator有效时,reverse_iterator才有效。”在我看来,主要的混淆点是由reverse_iterator包裹的实际Iterator指向的位置比reverse_iterator似乎指向的位置晚。 -
我只是好奇为什么你有那么多关于向量集合和
std::map<C, std::pair<T::const_reverse_iterator, std::vector<T>&>>的词,而似乎所有问题的真正意义在于向量中的reverse_iterator是否会失效当它用于擦除元素时。还是我根本不理解真正的问题?