如何迭代一个向量
How to iterate over a vector?
我需要严格按照元素被推入的顺序迭代vector。对于我的特殊情况,最好使用迭代器,而不是遍历For -each循环,如下所示:
std::vector<int> vector;
for(int i = 0; i < vector.size(); i++)
//not good, but works
我的问题是,像这样通过迭代器遍历向量是否可行:
std::vector<int> v;
for(typename std::vector<int>::iterator i = v.iterator(); i != v.end(); i++)
//good, but I'm not strictly sure about the iterating order.
那么,我可以安全地使用迭代器满足我的需求吗?是标准化的吗?
如果你能访问c++ 11,你可以使用基于范围的for循环
for (auto i : v)
否则应该使用begin()
和end()
for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++i)
您也可以使用std::begin
和std::end
(这些也需要c++ 11)
for (std::vector<int>::iterator i = std::begin(v); i != std::end(v); ++i)
begin
将返回指向vector中的第一个元素的迭代器。end
将返回一个迭代器,指向vector末尾后一个元素的。因此,以这种方式获得元素的迭代顺序既安全又有定义。
如果你想使用迭代器,你的方法是好的
for(auto it = v.begin(); it != v.end(); ++it)
的迭代顺序实际上取决于容器和实际使用的迭代器。对于std::vector,这段代码总是迭代vector中元素的顺序。如果您使用v.rbegin()或v.rend(),则顺序将颠倒。对于另一个容器,顺序是不同的,对于std::set,相同的代码将按照元素的排序条件升序迭代元素。
这是一个过于复杂的解决方案。
首先,我们从index
类型开始。它可以存储任何建模迭代器和/或整型(基本上,支持+标量,增量到标量,复制,销毁和相等):
template<class T,
class Category=std::random_access_iterator_tag,
class Delta=decltype(std::declval<T>()-std::declval<T>())
>
struct index:
std::iterator<Category, T, Delta, T*, T>
{
T t;
T operator*()const{ return t; }
index& operator++(){++t; return *this;}
index operator++(int){index tmp = *this; ++t; return tmp;}
index& operator--(){--t; return *this;}
index operator--(int){index tmp = *this; --t; return tmp;}
T operator[](size_t i)const{return t+i;}
friend bool operator<(index const& lhs, index const& rhs) {
return rhs.t-lhs.t>0;
}
friend bool operator>(index const& lhs, index const& rhs) {
return rhs<lhs;
}
friend bool operator<=(index const& lhs, index const& rhs) {
return !(lhs>rhs);
}
friend bool operator>=(index const& lhs, index const& rhs) {
return !(lhs<rhs);
}
friend bool operator==(index const& lhs, index const& rhs) {
return lhs.t==rhs.t;
}
friend bool operator!=(index const& lhs, index const& rhs) {
return lhs.t!=rhs.t;
}
friend Delta operator-(index const& lhs, index const& rhs) {
return lhs.t-rhs.t;
}
friend index& operator+=(index& lhs, Delta rhs) {
lhs.t+=rhs;
return lhs;
}
friend index& operator-=(index& lhs, Delta rhs) {
lhs.t-=rhs;
return lhs;
}
friend index operator+(index idx, Delta scalar) {
idx+=scalar;
return idx;
}
friend index operator+(Delta scalar, index idx) {
idx+=scalar;
return idx;
}
friend index operator-(index idx, Delta scalar) {
idx-=scalar;
return idx;
}
};
其中大部分是不需要的,但我想要完整。请注意,这声称默认情况下是一个随机访问迭代器,但它是假的,因为它的引用类型不是引用。我认为这个谎言值得。
使用index
,既可以创建迭代器-迭代器-迭代器,也可以创建迭代器-迭代器。下面是我们如何创建迭代器-复迭代器:
using it_category=typename std::iterator_traits<It>::iterator_category;
template<class It, class Category=it_category<It>>
index<It, Category> meta_iterator( It it ) { return {it}; }
接下来,我们希望能够使用一些迭代器,并遍历该范围。这意味着我们需要一个范围类型:
template<class It>
struct range {
It b, e;
range(It s, It f):b(s),e(f){}
range():b(),e(){}
It begin()const{return b;}
It end()const{return e;}
bool empty()const{return begin()==end();}
template<class R>
range(R&& r):range(std::begin(r),std::end(r)){}
};
这是一个trait,它接受一个可迭代的范围(不仅是range
,还包括任何容器),并获得迭代器类型。请注意,一个高级的支持adl的将是一个好主意:
template<class R>
using iterator=decltype(std::begin(std::declval<R&>()));
随机助手:template<class R,class It=iterator<R>>
range<It> make_range(R&&r){ return {std::forward<R>(r)}; }
template<class It
range<It> make_range(It s, It f){return {s,f};}
这是一个很有用的帮助,可以解决我们的问题:
template<class R>
range<meta_iterator<iterator<R>> iterators_into( R&& r ){
return {meta_iterator(std::begin(r)), meta_iterator(std::end(r))};
}
,我们完成了:
std::vector<int> v;
for(auto it: iterators_into(v)) {
}
返回v
的每个元素的迭代器。
对于工业质量,你会想要adl改进。此外,处理输入范围的右值存储可以让您在for(:)
循环中更好地链接范围适配器。
- 函数向量_指针有不同的原型,我可以构建一个吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 获取向量C++中第一个值和最后一个值的和
- 从多个源构造一个对象,包括一个对象向量
- 为什么一个向量上的多线程操作很慢
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 如何在 C++11 中查找和更新向量中的一个嵌套结构
- Lower_bound不适用于具有 3 个元素的向量的最后一个元素
- 将一个向量插入另一个向量的某个位置
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 将指向给定子类的指针从一个向量复制到另一个向量
- 如何创建一个类,以便向量工作 std::vector<MyClass<int>> v{ 1,2,3 };
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 将向量之间的数字放在另一个向量之间<vector>>如果两个数字的差值为 1
- 如何在不复制的情况下将一个向量移动到另一个向量中
- 创建一个函数的 Python 绑定,返回指向带有 boost 的向量的指针
- 紧凑向量一个小的内存足迹向量