【问题标题】:Idioms for iterating a sequential collection用于迭代顺序集合的习惯用法
【发布时间】:2013-01-02 21:46:00
【问题描述】:

在现代 C++ 中,当您只需要每个元素的值时,用于迭代像字符串或向量这样的顺序集合的习惯用法是简短而优雅的:

for (auto x: xs)

当你还需要索引时,它就没有那么优雅了:

for (size_t i = 0; i != xs.size() ++i)

...除非最近有一些我还没有赶上的发展。 C++11 是否有首选的方式来做后者,还是上面的方式仍然像它一样好?

【问题讨论】:

  • 使用 zip_iterator 来压缩你的迭代器和counting_iterator怎么样?你可以编写一个通用的容器包装类来处理这种类型的迭代器。

标签: c++ iteration


【解决方案1】:

Range-Based for loops 将在现代代码中非常流行,Range-Based for Loops 适用于任何支持范围概念的类型。给定 T 类型的对象 obj,begin(obj)end(obj) 是有效的。 包括:

  • 所有 C++11 库容器。
  • 数组和 valarray。
  • 初始化器列表。
  • 正则表达式匹配。
  • 任何 UDT(用户定义类型)T,其中 begin(T) 和 end(T) 产生合适的迭代器。

【讨论】:

    【解决方案2】:

    首选且惯用的方式是简单的 for 循环。

    替代方法包括使用整数范围:

    template<typename C>
    auto container_index(C const& container) -> decltype(boost::irange(0, container.size())) {
      return boost::irange(0, container.size());
    }
    
    for(auto x : container_index(xs))
    

    或者一个迭代函数:

    template<typename F>
    void index_iterate(std::size_t size, F func) {
      for(std::size_t i = 0; i != size; ++i) {
        func(i);
      }
    }
    
    index_iterate(container.size(), [&](std::size_t i){ /* ... */ });
    

    尽可能地使用简单的循环。在我看来它是优越的。

    【讨论】:

      【解决方案3】:

      你可以结合两种方法:

      int i = 0;
      for ( auto x : v ) {
          // do smth with x or v[i] or i
          i++;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-04-28
        • 2020-11-21
        • 1970-01-01
        • 2015-12-08
        • 2019-12-26
        • 2015-02-17
        • 1970-01-01
        相关资源
        最近更新 更多