컨테이너의 인덱싱에 대한 일반적인 개념으로 반복자를 좋아하는 이유를 설명하는 답변이 없습니다. 반복자를 사용한 대부분의 경험은 실제로 C ++이 아니라 Python과 같은 고급 프로그래밍 언어에서 온 것입니다.
반복자 인터페이스는 기능 소비자에게 더 적은 요구 사항을 부과하므로 소비자는 더 많은 기능을 수행 할 수 있습니다.
당신이 필요로하는 모든이 전달-반복 처리를 할 수있는 경우, 개발자는 색인 컨테이너를 사용에 제한되지 않는다 - 그들이 구현하는 어떤 클래스를 사용할 수 있습니다 operator++(T&)
, operator*(T)
하고 operator!=(const &T, const &T)
.
#include <iostream>
template <class InputIterator>
void printAll(InputIterator& begin, InputIterator& end)
{
for (auto current = begin; current != end; ++current) {
std::cout << *current << "\n";
}
}
// elsewhere...
printAll(myVector.begin(), myVector.end());
알고리즘은 벡터를 반복하여 필요한 경우에 작동하지만 반드시 예상하지 않는 응용 프로그램에도 유용 할 수 있습니다.
#include <random>
class RandomIterator
{
private:
std::mt19937 random;
std::uint_fast32_t current;
std::uint_fast32_t floor;
std::uint_fast32_t ceil;
public:
RandomIterator(
std::uint_fast32_t floor = 0,
std::uint_fast32_t ceil = UINT_FAST32_MAX,
std::uint_fast32_t seed = std::mt19937::default_seed
) :
floor(floor),
ceil(ceil)
{
random.seed(seed);
++(*this);
}
RandomIterator& operator++()
{
current = floor + (random() % (ceil - floor));
}
std::uint_fast32_t operator*() const
{
return current;
}
bool operator!=(const RandomIterator &that) const
{
return current != that.current;
}
};
int main()
{
// roll a 1d6 until we get a 6 and print the results
RandomIterator firstRandom(1, 7, std::random_device()());
RandomIterator secondRandom(6, 7);
printAll(firstRandom, secondRandom);
return 0;
}
이터레이터와 비슷한 것을 수행하는 대괄호 연산자를 구현하려고 시도하는 것이 고려되는 반면, 이터레이터 구현은 비교적 간단합니다. 대괄호 연산자는 클래스의 기능에 영향을 미치므로 임의의 지점으로 색인을 생성 할 수 있습니다. 이는 구현하기 어렵거나 비효율적 일 수 있습니다.
반복자들은 또한 장식에 적합하다 . 사람들은 자신의 생성자에서 반복자를 가져와 기능을 확장하는 반복자를 작성할 수 있습니다.
template<class InputIterator, typename T>
class FilterIterator
{
private:
InputIterator internalIterator;
public:
FilterIterator(const InputIterator &iterator):
internalIterator(iterator)
{
}
virtual bool condition(T) = 0;
FilterIterator<InputIterator, T>& operator++()
{
do {
++(internalIterator);
} while (!condition(*internalIterator));
return *this;
}
T operator*()
{
// Needed for the first result
if (!condition(*internalIterator))
++(*this);
return *internalIterator;
}
virtual bool operator!=(const FilterIterator& that) const
{
return internalIterator != that.internalIterator;
}
};
template <class InputIterator>
class EvenIterator : public FilterIterator<InputIterator, std::uint_fast32_t>
{
public:
EvenIterator(const InputIterator &internalIterator) :
FilterIterator<InputIterator, std::uint_fast32_t>(internalIterator)
{
}
bool condition(std::uint_fast32_t n)
{
return !(n % 2);
}
};
int main()
{
// Rolls a d20 until a 20 is rolled and discards odd rolls
EvenIterator<RandomIterator> firstRandom(RandomIterator(1, 21, std::random_device()()));
EvenIterator<RandomIterator> secondRandom(RandomIterator(20, 21));
printAll(firstRandom, secondRandom);
return 0;
}
이러한 장난감은 평범 해 보이지만 반복자와 반복자 데코레이터를 사용하여 간단한 인터페이스로 강력한 작업을 수행하는 것을 상상하는 것은 어렵지 않습니다. 예를 들어 단일 결과에서 모델 객체를 생성하는 반복자로 데이터베이스 결과의 순방향 전용 반복자를 장식 . 이 패턴은 무한 세트의 메모리 효율적인 반복을 가능하게하며, 위에서 쓴 것과 같은 필터를 사용하여 잠재적으로 결과에 대한 게으른 평가가 가능합니다.
C ++ 템플릿의 강력한 기능 중 하나는 고정 길이 C 배열에 적용 할 때 간단하고 효율적인 포인터 산술로 분해되어 실제로 비용이없는 추상화로 만드는 반복자 인터페이스 입니다.
some_iterator++
하는 것++some_iterator
입니다. 증가 후 불필요한 임시 반복자가 작성됩니다.