向量子集的迭代器

Iterator for a subset of a vector

是否可以从一个vector中得到一个const迭代器,这个vector在失效前只能迭代一定范围的vector?

例如,如果我有一个包含 10 个元素的向量,我想 return 一个包含 4 到 7 个元素的迭代器。

伪代码:

int main()
{
    std::vector<int> vector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    auto iterator = GetRangedIterator(vector, 4, 7)
    for (const int& num : iterator)
        print num;      // 4, 5, 6, 7
}

标准库中没有任何内容可以明确执行此操作,但如果您愿意使用 Boost,则可以使用以下使用 range 概念的方法:

auto range = boost::make_iterator_range(v.begin()+3, v.begin()+7);

BOOST_FOREACH(int i, range)
{
    cout << i << endl;
}

这应该输出 4567

这很简单(尽管我将结果称为范围,而不是迭代器)。

一个简单的实现看起来像这样:

template <class Iter>
class range {
    Iter b;
    Iter e;
public:

    range(Iter b, Iter e) : b(b), e(e) {}

    Iter begin() { return b; }
    Iter end() { return e; }
};

template <class Container>
range<typename Container::iterator> 
make_range(Container& c, size_t b, size_t e) {
    return range<typename Container::iterator> (c.begin()+b, c.begin()+e);
}

就目前而言,这遵循正常的 C++ 约定(从 0 开始计数,您指定的结束超出范围的结束,而不是在范围内)所以要获得您要求的输出,您需要指定 3, 7 的范围,例如:

for (int num : make_range(vector, 3, 7))
    std::cout << num << ", ";      // 4, 5, 6, 7,

请注意,基于范围的 for 循环知道如何使用 beginend 成员函数来告诉它要迭代的范围,所以我们没有要处理无效的迭代器或类似的东西,我们只需要指定我们关心的范围的开始和结束。

您可以使用 range-v3 library that is the bases of a Ranges TS which will been part of C++20,但该库已经适用于 C++11 编译器。方法如下:

#include <range/v3/all.hpp>
#include <iostream>
#include <vector>

int main() 
{
    using namespace ranges;

    auto v = view::iota(1, 11) | to_<std::vector<int>>();
    std::cout << view::all(v)  << '\n';

    auto rng = v | view::slice(3, 7); 
    std::cout << rng << '\n';
}

Live Example.

你可以用这个

for( it = v1.begin() + a; it <= v1.begin() + b; it++ )

下面的代码是一个小演示

#include <vector>
#include <iostream>

using namespace std;

int main(){

  vector<int> v1;

  for( int i = 0; i < 50; i++ ){
    v1.push_back( 2*(i+1) );
    cout<<v1.at(i)<<"   ";
  }
  cout<<endl;


  vector<int>::iterator it;

  int a = 5;
  int b = 9;

  for( it = v1.begin() + a; it <= v1.begin() + b; it++ ){

    cout<<(*it)<<"   ";
  }
  cout<<endl; 
}

输出为

2   4   6   8   10   12   14   16   18   20   22   24   26   28   30   32   34   36   38   40   42   44   46   48   50   52   54   56   58   60   62   64   66   68   70   72   74   76   78   80   82   84   86   88   90   92   94   96   98   100   
12   14   16   18   20   

您可以使用 :

auto first_index = 3;
auto last_index = 6;
auto count = last_index - first_index + 1;
auto interesting_nums = gsl::make_span(std::cbegin(vector) + start_index, count);
for(auto& num : interesting_nums) { /* do stuff */ }

备注:

  • 在您的示例中,您得到了第 4 到第 7 个元素,即索引 3 到 6,这是我在这里使用的。
  • 这段代码应该适用于任何容器,而不仅仅是矢量。
  • spans 是 GSL 的一部分,支持库为 C++ Core Guidelines。他们可能会在2020年正式进入C++标准,并受到社区的好评。