如果这是一个琐碎的问题,请原谅我,我只是在学习C++并试图理解某些概念。特别是当涉及到迭代器时,我完全迷失了。
假设我有一个自定义类来表示一些数据结构,并且其中一个成员是整数向量。我想为该类编写一个双向迭代器,仅输出向量中的偶数。有没有简单而有启示性的方法?我希望不要使用STL以外的库。
如果你不确定如何自己编写迭代器,那么最好使用条件语句for_each
函数。
std::for_each
可以对每个元素执行操作。很容易创建一个for_each_if
对特定元素执行操作。例如,下面的程序仅打印向量中的偶数(4、6和8)。
#include <iostream>
#include <vector>
using namespace std;
struct is_even {
typedef bool return_type;
bool operator() (const int& value) {return (value%2)==0; }
};
struct doprint {
bool operator() (const int& value) { std::cout << value << std::endl; }
};
template <class InputIterator, class Predicate, class Function>
void for_each_if(InputIterator first, InputIterator last, Function f, Predicate pred)
{
while ( first != last )
{
if (pred (*first))
f(*first++);
else
first ++;
}
}
int main()
{
std::vector<int> v;
v.push_back( 4 );
v.push_back( 5 );
v.push_back( 6 );
v.push_back( 8 );
for_each_if( v.begin(), v.end(), doprint(), is_even());
return 0;
}
vector::iterator
派生可能是最简单的方法:class my_iterator : private std::vector<int>::iterator {
typedef std::vector<int>::iterator base;
base m_base_end; // Stores the real end iterator of the internal vector.
// We need it so that the even/odd checking code
// doesn't run off the end of the vector
// (initialize it in a constructor, omitted here for
// brevity).
public:
using base::operator*;
using base::operator->;
// etc. for other members...
// except for increment:
my_iterator& operator++()
{
do {
base::operator++();
} while( static_cast<base&>(*this) != m_base_end
&& base::operator*() % 2 );
return *this;
}
my_iterator operator++(int)
{
my_iterator temp;
operator++();
return temp;
}
// TODO: decrement and other arithmetic operators
};
这还是相当多的样板代码,您还需要为 const_iterator
做同样的事情(我可能会将上述类作为模板使其更容易)。
考虑使用Boost - 它有专门为此目的设计的 filter_iterator
。如果不适合您,也可以考虑使用 iterator_adaptor
。
erase
也应该被覆盖:my_iterator iter = v.begin(); while ( iter != v.end() ) { if ( cond ) ++iter; else iter = v.erase(); }
。此外,vector::operator++
是virtual
的吗?因为非虚函数不应该被覆盖... - jpo38
#include <vector>
#include <iostream>
class X {
public:
class EvenIterator {
public:
EvenIterator(std::vector<int>::iterator it, std::vector<int>::iterator end) : it(it), end(end) {
while (true) {
if (isEven(*it)) {
break;
} else if (it == end) {
break;
}
it++;
}
}
bool operator != (const EvenIterator& evenIt) {
return evenIt.it != this->it;
}
int operator * () {
return *it;
}
EvenIterator operator ++ () {
while (true) {
it++;
if (isEven(*it)) {
return EvenIterator(it, end);
} else if (it == end) {
return EvenIterator(it, end);
}
}
}
private:
std::vector<int>::iterator it;
std::vector<int>::iterator end;
};
static bool isEven(int number) {
return number % 2 == 0;
}
void add(int number) {
v.push_back(number);
}
EvenIterator evenBegin() {
return EvenIterator(v.begin(), v.end());
}
EvenIterator evenEnd() {
return EvenIterator(v.end(), v.end());
}
private:
std::vector<int> v;
};
int main() {
X x;
x.add(1);
x.add(2);
x.add(3);
x.add(2);
x.add(2);
x.add(31);
x.add(56);
x.add(101);
for (X::EvenIterator it = x.evenBegin(); it != x.evenEnd(); ++it){
std::cout << *it << std::endl; // only prints the even numbers
}
}
iterator evenBegin() { std::vector<int>::iterator i = data.begin(); while (!isEven(*i)){ ++i; } return iterator(i, data.end()); }
。 - user32849
copy_if(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "), [](int i){ return (i % 2) == 0; });
- Neil Kirk