C++ 使用基于范围的 for 循环时需要迭代器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6953128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Need iterator when using ranged-based for loops
提问by u359653
Currently, I can only do ranged based loops with this:
目前,我只能用这个做基于范围的循环:
for (auto& value : values)
But sometimes I need an iterator to the value, instead of a reference (For whatever reason). Is there any method without having to go through the whole vector comparing values?
但有时我需要一个值的迭代器,而不是一个引用(无论出于何种原因)。有没有什么方法不需要通过整个向量比较值?
采纳答案by Nawaz
Use the old for
loop as:
使用旧for
循环作为:
for (auto it = values.begin(); it != values.end(); ++it )
{
auto & value = *it;
//...
}
With this, you've value
as well as iterator it
. Use whatever you want to use.
有了这个,你value
和 iterator 一样it
。想用什么就用什么。
EDIT:
编辑:
Although I wouldn't recommended this, but if you want to use range-based for
loop (yeah, For whatever reason:D), then you can do this:
虽然我不推荐这样做,但是如果您想使用基于范围的for
循环(是的,无论出于何种原因:D),那么您可以这样做:
auto it = std::begin(values); //std::begin is a free function in C++11
for (auto& value : values)
{
//Use value or it - whatever you need!
//...
++it; //at the end OR make sure you do this in each iteration
}
This approach avoids searching given value
, since value
and it
are always in sync.
这种方法避免了搜索 given value
,因为value
和it
总是同步的。
回答by Potatoswatter
Here is a proxy wrapper class to allow you to expose the hidden iterator by aliasing it to your own variable.
这是一个代理包装器类,允许您通过将其别名为您自己的变量来公开隐藏的迭代器。
#include <memory>
#include <iterator>
/* Only provides the bare minimum to support range-based for loops.
Since the internal iterator of a range-based for is inaccessible,
there is no point in more functionality here. */
template< typename iter >
struct range_iterator_reference_wrapper
: std::reference_wrapper< iter > {
iter &operator++() { return ++ this->get(); }
decltype( * std::declval< iter >() ) operator*() { return * this->get(); }
range_iterator_reference_wrapper( iter &in )
: std::reference_wrapper< iter >( in ) {}
friend bool operator!= ( range_iterator_reference_wrapper const &l,
range_iterator_reference_wrapper const &r )
{ return l.get() != r.get(); }
};
namespace unpolluted {
/* Cannot call unqualified free functions begin() and end() from
within a class with members begin() and end() without this hack. */
template< typename u >
auto b( u &c ) -> decltype( begin( c ) ) { return begin( c ); }
template< typename u >
auto e( u &c ) -> decltype( end( c ) ) { return end( c ); }
}
template< typename iter >
struct range_proxy {
range_proxy( iter &in_first, iter in_last )
: first( in_first ), last( in_last ) {}
template< typename T >
range_proxy( iter &out_first, T &in_container )
: first( out_first ),
last( unpolluted::e( in_container ) ) {
out_first = unpolluted::b( in_container );
}
range_iterator_reference_wrapper< iter > begin() const
{ return first; }
range_iterator_reference_wrapper< iter > end()
{ return last; }
iter &first;
iter last;
};
template< typename iter >
range_proxy< iter > visible_range( iter &in_first, iter in_last )
{ return range_proxy< iter >( in_first, in_last ); }
template< typename iter, typename container >
range_proxy< iter > visible_range( iter &first, container &in_container )
{ return range_proxy< iter >( first, in_container ); }
Usage:
用法:
#include <vector>
#include <iostream>
std::vector< int > values{ 1, 3, 9 };
int main() {
// Either provide one iterator to see it through the whole container...
std::vector< int >::iterator i;
for ( auto &value : visible_range( i, values ) )
std::cout << "# " << i - values.begin() << " = " << ++ value << '\n';
// ... or two iterators to see the first incremented up to the second.
auto j = values.begin(), end = values.end();
for ( auto &value : visible_range( j, end ) )
std::cout << "# " << j - values.begin() << " = " << ++ value << '\n';
}
回答by payload
I tried myself on this and found a solution.
我对此进行了尝试并找到了解决方案。
Usage:
用法:
for(auto i : ForIterator(some_list)) {
// i is the iterator, which was returned by some_list.begin()
// might be useful for whatever reason
}
The implementationwas not that difficult:
实现并不难:
template <typename T> struct Iterator {
T& list;
typedef decltype(list.begin()) I;
struct InnerIterator {
I i;
InnerIterator(I i) : i(i) {}
I operator * () { return i; }
I operator ++ () { return ++i; }
bool operator != (const InnerIterator& o) { return i != o.i; }
};
Iterator(T& list) : list(list) {}
InnerIterator begin() { return InnerIterator(list.begin()); }
InnerIterator end() { return InnerIterator(list.end()); }
};
template <typename T> Iterator<T> ForIterator(T& list) {
return Iterator<T>(list);
}
回答by Ragesh Chakkadath
range basedfor
loop is created as the c++ counterpart for foreach
in java that allows easy iteration of array elements. It is meant for removing the usage of complex structures like iterators so as to make it simple. I you want an iterator
, as Nawaz said, you will have to use normal for
loop.
基于范围的for
循环被创建为foreach
java 中的 c++ 对应物,它允许轻松迭代数组元素。它旨在消除迭代器等复杂结构的使用,使其变得简单。我想要一个iterator
,正如 Nawaz 所说,你将不得不使用普通for
循环。
回答by PulseJet
There is a very simple way of doing this for std::vector
, which should also work if you are resizing the vector during the process (I'm not sure whether the accepted answer considers this case)
有一种非常简单的方法可以做到这一点std::vector
,如果您在此过程中调整向量的大小,它也应该有效(我不确定接受的答案是否考虑了这种情况)
If b
is your vector, you can just do
如果b
是你的载体,你可以做
for(auto &i:b){
auto iter = b.begin() + (&i-&*(b.begin()));
}
where iter
will be your required iterator.
iter
你需要的迭代器在哪里。
This takes advantage of the fact that C++ vectors are always contiguous.
这利用了C++ 向量始终是连续的这一事实。
回答by mbusch
Let's do it very dirty ... I know, the 0x70h is changing with stack-usage, compiler version, .... It should be exposed by the compiler, but it is not :-(
让我们做得很脏......我知道,0x70h 正在随着堆栈使用、编译器版本等而变化......它应该由编译器公开,但它不是:-(
char* uRBP = 0; __asm { mov uRBP, rbp }
Iterator** __pBegin = (Iterator**)(uRBP+0x70);
for (auto& oEntry : *this) {
if (oEntry == *pVal) return (*__pBegin)->iPos;
}