当前位置: 首页 > 知识库问答 >
问题:

基于向量的范围内项目索引的获取

高迪
2023-03-14

C 11引入了基于ranged的for循环,该循环在内部使用(const)迭代器实现,因此:

std::vector<std::string> vec;

for(std::string &str : vec)
{
//...
}

基本上相当于更详细(是的,可以使用auto简化):

for(std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it)
{
//...
}

然而,通常需要一个项目的索引。第二种方法很简单:

auto index = it - vec.begin();

在基于范围的for中,它不是那么简单。但我想知道这是否是一个可以完全避免迭代器的便携解决方案:

for(auto &str : vec)
{
    auto index = &str - &vec[0];
}

const版本将是相同的,但需要注意不要将非const容器与const引用混合,这可能并不总是显而易见的。)

显然,这依赖于几个假设:

>

  • 向量的迭代器只是对一个项的引用(可能在标准中?)

    容器保证连续(std::向量是...)

    基于范围的for的内部实现(也可能在标准中)

  • 共有2个答案

    刁钧
    2023-03-14

    是的,这是一个有效的解决方案。底层数据保证是连续的(std::向量应该或多或少是一个动态数组)。

    n4140§23.3。6.1[向量概述]/1

    向量的元素是连续存储的,这意味着如果v向量

    解河
    2023-03-14

    是的,但我会使用vec。改为data()。使用的好处。data()是指非连续的std容器没有它,因此当被迭代的容器不能以这种方式工作时(如dequestd::vector),代码可靠地停止编译

    或者我们写一个index_t类似迭代器的包装器:

    template<class T>
    struct index_t {
      T t;
      T operator*()const{ return t; }
      void operator++() { ++t; }
      friend bool operator==( index_t const& lhs, index_t const& rhs ) {
        return lhs.t == rhs.t;
      }
      friend bool operator!=( index_t const& lhs, index_t const& rhs ) {
        return lhs.t != rhs.t;
      }
    };
    template<class T>
    index_t<T> index(T t) { return {t}; }
    

    index\t

    index\t

    template<class It>
    struct range_t {
      It b,e;
      It begin() const {return b;}
      It end() const {return e;}
    };
    template<class It>
    range_t<It> range( It s, It f ) { return {s,f}; }
    
    template<class T>
    range_t<index_t<T>>
    index_over( T s, T f ) {
      return {{{s}}, {{f}}};
    }
    template<class Container>
    auto iterators_of( Container& c ) {
      using std::begin; using std::end;
      return index_over( begin(c), end(c) );
    }
    

    我们现在可以对容器的迭代器进行迭代器。

    for (auto it : iterators_of(vec))
    

    活生生的例子。

    提到的迭代整数是:

    for (int i : index_over( 0, 100 ) )
    

    我们也可以直接得到容器的索引:

    template<class Container>
    range_t< index_t<std::size_t> >
    indexes_of( Container& c ) {
      return index_over( std::size_t(0), c.size() );
    }
    template<class T, std::size_t N>
    range_t< index_t<std::size_t> >
    indexes_of( T(&)[N] ) {
      return index_over( std::size_t(0), N );
    }
    

    这让我们:

    for( auto i : indexes_of( vec ) )
    

    其中i0变化到vec.size()-1。我发现这有时比zip迭代器之类的更容易使用。

    省略的改进:

    使索引\u t成为真正的输入迭代器。根据需要使用std::move和/或std::forward创建索引和范围。支持范围上的哨兵。使范围界面更丰富(大小,可选随机访问[]范围:无前(n)常数,等等。

     类似资料:
    • 阅读一些基于范围的循环示例,他们提出了两种主要方法1、2、3、4 或 好 当我们不需要更改项目时,IMO的示例建议使用第二个版本(按值)。为什么他们不建议引用的内容(至少我没有找到任何直接的建议): 不是更好吗?当它是一个

    • C 11 使用基于范围的for循环对作为类成员的std::向量进行迭代的代码是什么?我尝试了以下几个版本:

    • 问题内容: 有没有办法获取所有当前在javascript范围内的变量? 问题答案: 否。“范围内”变量由“作用域链”确定,该变量无法通过编程方式访问。 有关详细信息(很多),请查看ECMAScript(JavaScript)规范。这是指向官方页面的链接,您可以在其中下载规范规范(PDF),而这是指向官方的可链接HTML版本的链接。 根据您对Camsoft的评论进行更新 事件函数作用 域中 的变量取

    • 问题内容: 例如,我有一个数字数组 我想找到特定范围内元素的所有索引。例如,如果范围是(6,10),则答案应该是(3,4,5)。有内置的功能可以做到这一点吗? 问题答案: 您可以用来获取索引并设置两个条件:

    • 问题内容: 我如何让SQL重复一些基于集合的操作任意次数而不会循环?如何让SQL对一定范围的数字执行运算?我基本上是在寻找一种基于集合的for循环的方法。 我知道我可以创建一个包含整数(例如1到1000)的小表,然后将其用于该范围内的范围操作。 例如,如果我有该表,则可以选择查找数字100-200的总和,如下所示: 有任何想法吗?我有点在寻找适用于T-SQL的东西,但是任何平台都可以。 问题答案:

    • 我对C很陌生,现在就在做中学习。在课堂材料中,我有以下功能: 几分钟前,我像这样使用了普通for循环: