【问题标题】:Get index in vector from reverse iterator从反向迭代器获取向量中的索引
【发布时间】:2014-09-19 19:09:09
【问题描述】:

我知道如何从向量迭代器中获取索引,方法是从中减去开始迭代器。例如:

vector<int>::iterator it = find(vec.begin(), vec.end(), x);
size_t position = it - vec.begin();

但是,现在我想找到向量中最后一个x 的索引。如何从反向迭代器中获取真实索引?我发现以下似乎有效(编辑:它没有)但也许有更好的(更惯用的或其他......)方式。

vector<int>::reverse_iterator it = find(vec.rbegin(), vec.rend(), x);
size_t position = vec.size() - (it - vec.rbegin());

【问题讨论】:

标签: c++ vector iterator find reverse-iterator


【解决方案1】:

你可以使用:

container.size() - 1 - (iterator - container.rbegin())

container.size() - 1 - std::distance(container.rbegin(), iterator)

有关反向迭代器的更多信息。 How To Use Reverse Iterators Without Getting Confused。将反向迭代器转换为正向迭代器等等。

【讨论】:

  • 这行得通,但如果找不到值,它会给出一个溢出的值。这对我来说很好测试它被发现了,但它是安全的吗?
  • 问题是当container.size() == 0 时,当找不到值时会给你一个拥有.end() 的索引,我认为它与迭代器end() 非常相似,索引将是 == .size()。
【解决方案2】:

我会使用:

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
    auto v = std::vector<int> { 1, 2, 3 };
    auto rit = std::find(v.rbegin(), v.rend(), 3);
    if (rit != v.rend()) {
        auto idx = std::distance(begin(v), rit.base()) - 1;
        std::cout << idx;
    } else
        std::cout << "not found!";
}

Live Example.

距离计算中-1的原因是因为.base()成员中反向迭代器和常规迭代器之间的转换:

24.5.1 反向迭代器 [reverse.iterators]

1 类模板 reverse_iterator 是一个迭代器适配器,用于迭代 从由其底层迭代器定义的序列的末尾到 该序列的开始。反向之间的基本关系 迭代器及其对应的迭代器 i 由 身份:&amp;*(reverse_iterator(i)) == &amp;*(i - 1)

注意:您也可以使用上面的代码而不检查v.rend(),并使用idx == -1 等同于未找到元素的约定。但是,这将失去执行v[idx] 的能力,因此最终您还需要对其进行检查。

【讨论】:

  • 我的 idx 未签名。当未找到值时,距离返回 -1 并溢出到大数字。但我可以将其与 >= size 进行比较,看看是否找不到。这安全吗?
  • @NeilKirk,是的,您必须单独处理。在.rend().base() 上使用std::prev 是未定义的行为AFAIK。
【解决方案3】:

我会将 TemplateRex 的答案更改为仅使用反向迭代器,从而避免任何因反向正向转换而令人头疼的问题。

int main()
{
    auto v = std::vector<int> { 1, 2, 3 };
    auto rit = std::find(v.rbegin(), v.rend(), 3);
    if (rit != v.rend()) {
        auto idx = std::distance(rit, v.rend()) - 1;
        std::cout << idx;
    } else
        std::cout << "not found!";
}

-1 仍然需要,因为向量的第一个元素(索引 0)实际上位于 v.rend() - 1

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    相关资源
    最近更新 更多