基于c++11中的范围
range-based for in c++11
在c++11中,如果我们有一个set<int> S
;我们可以说:
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
值时,我们应该怎么做?我知道我们可以创建一个新的向量,但将一个向量复制到一个新向量需要时间。
不,很不幸。看看标准是怎么说的:
基于语句的范围for(用于范围声明:表达式)语句相当于
{ auto && __range = ( expression ); for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
其中__range、__begin和__end是为仅展示定义的变量
换句话说,它已经从begin
迭代到end
,并且已经取消了对迭代器的引用,这是您永远看不到的。
基于范围的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
}
不,你不能。
for (... : ...)
仅由于不引入新的关键字的原因而被称为CCD_ 10而不是CCD_。foreach
的全部要点是一个快速的简短语法,用于迭代所有元素而不关心它们的索引。对于所有其他情况,有一个简单的for
,它非常有效地达到了它的目的。
对于一般情况,您必须使用一个单独的变量:
int i = 0;
for (auto x : s)
cout << (i++ ? " " : "") << x << endl;
当然,对于某些容器(如vector
)也有一些技巧,但没有一个适用于每个容器。
为此,您最好使用普通的for
循环。
您不能在set
中。使用传统的for
语法或维护自己的索引计数器。
您可以在vector
或其他具有平面布局(如std::array
或C样式数组)的容器中。将其更改为使用引用:
for (auto &i: S)
然后可以将i
的地址与s[0]
的地址进行比较以获得索引。
基于范围的for
适用于简单的情况。我希望在原型化时能稍微有用一些,但我希望在东西真正成为产品之前很久,它的用途就已经消失了。让初学者的生活更轻松可能很有用,但这是一个我无法判断的领域(但这似乎推动了最近许多C++讨论)。
唯一有点建设性的方法是使用一个适配器,该适配器引用底层范围,并且其begin()
和end()
方法适当地调整迭代器。还要注意,您可能希望将对第一个或最后一个元素的任何特殊处理从处理大量数据的循环中提升出来。当然,这只是另一个检查,然后是正确预测的分支,而不是不检查,分支预测表的污染更少。
- C ++枚举范围无法使用-std=c ++ 98进行编译,但使用-std=c ++ 11可以
- C++11 基于范围的 for 循环,用于 std::list
- C++11:没有复制构造函数的自定义基于范围的循环
- 如何在C++11中区分填充构造函数和范围构造函数
- 自动和范围内 for 循环 C++11 不起作用
- 带钥匙的C 11地图定义了一个值范围
- 为什么即使在启用 C++11 并且我包含字符串之后,'stod'仍然没有在此范围内声明?
- C++11 迭代器和返回的 std::unique_ptr 的范围
- C++11:用容器参数定义函数(类似于基于范围的)
- 缩小 C++11 中的转换范围:"actual value after conversion"是什么?
- 范围/切片以 C++11/1y 为单位
- C 11矢量构造函数复制与范围
- C 11中的范围(故障)
- C 11中类范围的数组初始化
- 基于范围的循环:自动更改C 11中的含义
- GCC 4.4 不实现 C++11 范围循环.它还支持哪些其他范围循环语法
- 如何将基于迭代器的 for 循环重写为基于范围的循环 (C++11)
- 嵌套c++11范围循环,用于查找组合
- 更快的环路范围 (C++11)
- 警告:缩小转换范围 C++11