在矢量中的点开始基于范围的 for 循环
Have range-based for loop start at point in vector
我有指向某个类对象的指针std::vector<MyClass*> container
,并希望使用基于范围的 for 循环遍历向量,如下所示
for (MyClass *item : container)
{
// Do stuff, not changing the container
}
在这个循环中,我想再次遍历容器,但从容器中的下一个元素开始。如果没有迭代器,我真的找不到一种方法来做到这一点,所以我的解决方案是只使用它们
for (auto item1 = container.begin(); item1 != container.end(); ++item1)
{
for (auto item2 = item1.next(); item2 != container.end(); ++item2)
{
// Do stuff, not changing the container
}
}
我的问题是:有没有办法做到这一点,而不必求助于迭代器?我意识到基于范围的 for 循环只是语法糖,并且确实使用迭代器,但我喜欢我的语法糖!
(请注意下面的编辑)
for-range 循环不允许您访问内部迭代器。一方面,这很好,因为你不能搞砸它。另一方面,这可能很糟糕,因为您需要迭代器知道您在容器中的位置。因此,我们不能使用 for-range 循环作为外部循环,除非您使用线性内存布局迭代某些内容,您可以在其中将项目的地址作为迭代器。
此外,标准库还不能胜任以方便的方式处理范围的任务。我正在使用 Boost 的一些实用程序,例如iterator_range
用于此代码片段:
using boost::make_iterator_range;
using std::next;
for (auto iter1 = container.begin(), ee = container.end(); iter1 != ee; ++iter1) {
auto& item1 = *iter1;
for (auto& item2 : make_iterator_range(next(iter1),ee)) {
// do something with item1 and item2
}
}
诚然,不是很漂亮。但这显示了如何在给定一对迭代器的情况下使用 for-range 循环的一种方法。基本上,for-range循环吃掉任何提供开始/结束功能的东西。 make_iterator_range
包装一对迭代器并返回一些提供开始/结束函数的东西。
编辑:我最近了解到boost::irange
也可以生成迭代器序列(而不仅仅是数字序列)。考虑到这一点,请查看此程序:
#include <iostream>
#include <vector>
#include <boost/range/irange.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/indexed.hpp>
int main()
{
using std::vector;
using std::next;
using boost::irange;
using boost::make_iterator_range;
namespace ba = boost::adaptors;
vector<double> x {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
for (auto iter1 : irange(begin(x),end(x))) {
auto& item1 = *iter1;
for (auto& item2 : make_iterator_range(next(iter1),end(x))) {
// do something with item1 and item2
std::cout << item1 << " < " << item2 << std::endl;
}
}
return 0;
}
我在 C++0x 模式下使用 G++ 4.6.3 和 Boost 1.48 对此进行了测试,它确实有效。
根据 OP 的请求添加了我的评论作为答案。
没有迭代器,就无法做到这一点。但是你可以避免放弃迭代整个集合的语法糖,请参阅此答案。我还没有测试过该代码,但对该答案的评论建议 boost::counting_range,这可能会更好。
您可以创建一个将访问该范围的简单类:
#include <vector>
#include <iostream>
template<typename I>
struct Sub {
I _begin;
I _end;
Sub(I b, I e): _begin(b), _end(e) {}
I begin() const { return _begin; }
I end() const { return _end; }
};
template<typename I>
Sub<I> sub(I b, I e) { return Sub<I>(b, e); }
int main() {
std::vector<int> a{0,1,2,3,4,5,6,7,8,9};
for (auto i: sub(a.begin() + 3, a.end() - 1)) {
std::cout << i << "n";
}
}
此代码打印:
3
4
5
6
7
8
循环的范围迭代容器中的所有元素。这意味着您可以将该循环更改为:
for (auto item1 : container )
{
for (auto item2 = item1.next(); item2 != container.end(); ++item2)
{
// Do stuff, not changing the container
}
}
由于内部循环不会迭代整个容器,因此必须使用 normal for 循环。
- 基于范围循环到旧编译器的旧样式
- 带有自定义对象的C 范围循环
- 为什么编译器不优化集合元素上的空范围循环?
- 迭代在包含向量的vor in for for范围循环中迭代
- 我们可以在范围循环中使用引用(而不是指针)上的删除
- 如何实现我的自定义范围循环
- C++范围循环
- GCC 4.4 不实现 C++11 范围循环.它还支持哪些其他范围循环语法
- 嵌套c++11范围循环,用于查找组合
- 范围循环中的访问索引
- 对于不可复制类型的范围循环,是否可能
- 我的范围循环出现逻辑错误
- 如何在我的类上允许范围循环
- c++的范围循环比递减循环快
- 通过范围循环从指针容器中获取取消引用元素的引用
- c++ 11:为什么这个范围循环会使FPS下降35
- 带有自定义类的范围循环(矢量的简单版本<string>,使用分配器)
- MSVC10 Visual Studio 2010支持c++范围循环吗?
- 围绕 2 的幂范围循环变量
- toupper() 在 for 范围循环中不起作用