C数组的反向迭代器
Reverse iterators for C arrays
对于使用STL函数遍历C数组,std::begin
和std::end
函数是相当方便的.begin()
和.end()
等价函数。然而,对于双向C++容器,并没有std::rbegin
和std::rend
等效的反向迭代器。这样一个等价物是否以其他名称存在,或者很容易制作?我意识到一个困难是std::begin
通常返回一个原始指针,而对于相反的情况,这将需要一个包装器,这样++操作可能会过载。一个非常不完整的实现可能看起来像
template<class T>
class ReverseArrayIterator {
public:
ReverseArrayIterator(T* ptr) : _ptr(ptr) {}
operator T*() {
return _ptr;
}
void operator++() {
--_ptr;
}
T operator*() {
return *_ptr;
}
bool operator!= (ReverseArrayIterator& rhs) {
return _ptr != rhs._ptr;
}
private:
T* _ptr;
};
template<class T, size_t size>
ReverseArrayIterator<T> rbegin(T (&array)[size]) {
return ReverseArrayIterator<T>(&array[0] + size - 1);
}
template<class T, size_t size>
ReverseArrayIterator<T> rend(T (&array)[size]) {
return ReverseArrayIterator<T>(&array[0] - 1);
}
我用以下代码测试了这个基本实现:
int x[] = {1,2,3,4,5,6,0,0,0,10,11,12};
auto a = std::find(std::begin(x),std::end(x),0);
auto b = std::find(rbegin(x),rend(x),0);
cout << std::distance(x,a) << endl;
cout << std::distance(x,(int*)b) << endl;
这能被充实成一个完全可操作的C数组反向迭代器类吗?或者我会遇到更多的障碍吗?一个可能的障碍似乎是对原始指针的隐式转换,我希望它能用于std::distance这样的函数中——上面的代码段不会使用std::distance(x,b)
(或者类似的函数,可能)编译,但需要手动(int*)
转换。
(我将这些评论转化为帮助他人的答案。感谢chris和StoryTeller。)
从C++14开始,就有rbgin()和rend(),正如您所描述的那样。
还有一个适配器类,用于将(正向)迭代器转换为反向迭代器。请注意,正向begin()
迭代器应传递给make_reverse_iterator
,以使反向迭代器,反之亦然:
std::vector<int> v{ 1, 3, 10, 8, 22 };
std::copy(
std::make_reverse_iterator(v.end()),
std::make_reverse_iterator(v.begin()),
std::ostream_iterator<int>(std::cout, ", "));
使用span来包装您的数组,不必手动滚动您建议的代码。
Spans是内存中连续值序列的轻量级包装器,为您提供了标准库容器对这些值的所有"便利",包括反向迭代器、循环范围等
Spans已经成为C++20中的标准,但您询问了C++11,因此您可以使用C++指南支持库的span,例如从支持C++11的GSL lite实现(Microsoft的GSL没有)。
跨度是参考类型,非常轻,而且通常只是经过优化。因此,使用跨度通常不会花费任何费用。
在您的示例中,使用跨度,您可以按如下方式重写代码:
#include <iterator>
#include <gsl/gsl-lite.hpp>
#include <iostream>
int main()
{
int raw_x[] = {1, 2, 3, 4, 5, 6, 0, 0, 0, 10, 11, 12};
auto x = gsl::span<int>{raw_x};
auto a = std::find(x.begin(), x.end(),0);
auto b = std::find(x.rbegin(), x.rend(),0);
std::cout << std::distance(x.begin(), a) << std::endl;
std::cout << std::distance(x.rend(), b) << std::endl;
}
并编译(GodBolt)。
注意,我使用了rbegin()
和rend()
成员,而不是std::rbegin()
和std::rend()
,因为后者尚未在C++11中标准化。
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- 自定义 STL 兼容迭代器,用于迭代 2D 数组类的列
- 获取 c++ 中具有恒定长度的数组的迭代器
- 为自定义数组实现迭代器
- 原始数组和 std::array 在 clang++ 和 VC++ 上的不同迭代器行为
- C++程序在迭代到数组的最后一个元素时崩溃
- 有没有办法创建一个花哨的迭代器和相应的新数组,以便检查每个索引的索引值的条件?
- C 迭代器范围使用指针到数组
- 当大小未知时,如何迭代指向数组 (int*) 的指针?
- 是否可以在 C 数组中使用迭代器?
- 迭代器和数组
- STL 迭代器和数组的关系
- 使用迭代器数组读取稀疏信息
- 为什么迭代2D数组的行主要比列主要快
- c++ 11迭代锯齿数组
- 一元函数,接受迭代器元组并产生基本类型
- 迭代c++数组
- 迭代器元组.operator++的实现
- 如何在C和C++中迭代字符串数组
- 用step迭代1D数组和2D数组