使用基于范围的 for 循环遍历自定义容器
Custom container traversal with range-based for loop
在C++中,一些STL容器如vector、map、string可以通过带冒号的for循环遍历。
例如:
for(auto c:v)
写自定义容器的时候,能不能像Java那样遍历(只需要实现Iterable)?
是的,您需要实现某种形式的迭代器并覆盖 std::begin(container) 和 std::end(container)(如果您的容器具有 begin 和 end 方法,也可能有效)。
在内部,代码等同于以下内容(这只是为了说明问题,编译器的编写方式可能略有不同,有关详细信息,请参阅 here)。
auto _end = end(v);
for (auto _it = begin(v); _it != _end; ++_it) {
auto c = *_it;
<the rest of loop code>
}
因此,如果您的迭代器和覆盖按预期工作,它也适用于 for 循环。
您可以有以下简单的等同于 Java Iterable
接口:
template <typename T, typename U>
struct iterable {
T _begin;
U _end;
iterable(T begin, U end)
: _begin(begin),
_end(end)
{}
T begin() {
return _begin;
}
U end() {
return _end;
}
};
如果你想知道为什么开始迭代器和结束迭代器应该相同时会有 T
和 U
。原因是有些容器没有这两个相同类型的迭代器。
此外,您可以实现辅助函数 make_iterable
,例如:
template <typename T, typename U>
iterable<T, U> make_iterable(T t, U u) {
return iterable<T,U>(t, u);
}
在C++中,一些STL容器如vector、map、string可以通过带冒号的for循环遍历。
例如:
for(auto c:v)
写自定义容器的时候,能不能像Java那样遍历(只需要实现Iterable)?
是的,您需要实现某种形式的迭代器并覆盖 std::begin(container) 和 std::end(container)(如果您的容器具有 begin 和 end 方法,也可能有效)。
在内部,代码等同于以下内容(这只是为了说明问题,编译器的编写方式可能略有不同,有关详细信息,请参阅 here)。
auto _end = end(v);
for (auto _it = begin(v); _it != _end; ++_it) {
auto c = *_it;
<the rest of loop code>
}
因此,如果您的迭代器和覆盖按预期工作,它也适用于 for 循环。
您可以有以下简单的等同于 Java Iterable
接口:
template <typename T, typename U>
struct iterable {
T _begin;
U _end;
iterable(T begin, U end)
: _begin(begin),
_end(end)
{}
T begin() {
return _begin;
}
U end() {
return _end;
}
};
如果你想知道为什么开始迭代器和结束迭代器应该相同时会有 T
和 U
。原因是有些容器没有这两个相同类型的迭代器。
此外,您可以实现辅助函数 make_iterable
,例如:
template <typename T, typename U>
iterable<T, U> make_iterable(T t, U u) {
return iterable<T,U>(t, u);
}