基于范围的c ++ 11

时间:2012-01-25 16:02:43

标签: c++ gcc for-loop c++11

如果我们有set<int> S,则在c ++ 11中

;我们可以说:

for (auto i: S)
    cout << i << endl;

但是我们可以强制i成为迭代器,我的意思是编写一个等同于的代码:

for (auto i = S.begin(); i != S.end(); i++)
    cout << (i != s.begin()) ? " " : "" << *i;

或者我们可以做一些我们可以理解集合(或向量)中i索引的内容吗?

另一个问题是我们怎么说不要对S中的所有元素执行此操作,而是对其中的前半部分或除第一部分之外的所有元素执行此操作。

或当我们有vector<int> V时,想要打印其第一个n值,我们该怎么做?我知道我们可以创建一个新的向量,但是将一个向量复制到一个新的向量需要时间。

6 个答案:

答案 0 :(得分:20)

不,不幸的是。看看标准说的是什么:

  

基于范围的声明   for(range-declaration:expression)语句   相当于

{
    auto && __range = ( expression );
    for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) {
        for-range-declaration = *__begin;
        statement
    }
}
     

其中__range,__ begin和__end是仅为仅曝光定义的变量

换句话说,它已经从begin迭代到end,并且已经取消引用迭代器,你永远不会看到它。

答案 1 :(得分:9)

基于范围的for的原则是迭代整个范围。

决定范围是什么,因此你可以对范围本身进行操作。

template <typename It>
class RangeView {
public:
  typedef It iterator;

  RangeView(): _begin(), _end() {}
  RangeView(iterator begin, iterator end): _begin(begin), _end(end) {}

  iterator begin() const { return _begin; }
  iterator end() const { return _end; }

private:
  iterator _begin;
  iterator _end;
};

template <typename C>
RangeView<typename C::iterator> rangeView(C& c, size_t begin, size_t end) {
  return RangeView<typename C::iterator>(
           std::next(c.begin(), begin),
           std::next(c.begin(), end)
         );
}

template <typename C>
RangeView<typename C::const_iterator> rangeView(C const& c, size_t begin, size_t end) {
  return RangeView<typename C::const_iterator>(
           std::next(c.begin(), begin),
           std::next(c.begin(), end)
         );
}

好的,这严重地重新组合了Boost.Range ......

现在,让我们使用它!

for (auto i: rangeView(set, 1, 10)) {
  // iterate through the second to the ninth element
}

答案 2 :(得分:2)

不,你不能。

for (... : ...)
仅因为不引入新关键字而将

称为for而不是foreachforeach的全部内容是一种快速的短语法,用于迭代所有元素而无需关心它们的索引。对于所有其他情况,简单的for非常有效地发挥其作用。

答案 3 :(得分:2)

你不能<{1}} 。使用传统的set语法或维护自己的索引计数器。

您可以<{1}}或其他具有for平面布局或C风格数组的容器。将其更改为使用参考。

vector

然后,您可以将std::array的地址与for (auto &i: S) 的地址进行比较,以获取索引。

答案 4 :(得分:2)

对于一般情况,您必须使用单独的变量:

int i = 0;

for (auto x : s)
    cout << (i++ ? " " : "") << x << endl;

当然,某些容器(如vector)有一些技巧,但每个容器都没有。

为此目的,你可能最好使用普通的for循环。

答案 5 :(得分:0)

基于范围的for适用于简单情况。我希望在对原型进行原型设计时能够稍微有用,但是预计在实际成为产品之前,它的使用大部分都会消失。让初学者的生活更轻松可能是有用的,但这是一个我无法判断的领域(但似乎推动了很多最近的C ++讨论)。

唯一有点建设性的方法可能是使用引用基础范围的适配器,其begin()end()方法适当地调整迭代器。另请注意,您可能希望在处理大量数据的循环中提升对第一个或最后一个元素的任何特殊处理。当然,它只是另一个检查,然后是正确预测的分支与没有检查和分支预测表的污染较少。