Существует много разновидностей итераторов.
Например, в векторе итераторы обычно представляют собой простые указатели:
template <class T>
class Iterator
{
public:
T* operator->() { return m_pointer; }
private:
T* m_pointer;
};
Но это работает, потому что на самом деле вектор - это просто массив.
В двусвязном списке он будет другим, список будет состоять из узлов.
template <class T>
struct Node
{
Node* m_prev;
Node* m_next;
T m_value;
};
template <class T>
class Iterator
{
public:
T* operator->() { return m_node->m_value; }
private:
Node<T>* m_node;
};
Обычно вы хотите, чтобы итератор был как можно более легким, потому что они передаются по значению, поэтому имеет смысл указатель на базовый контейнер.
Возможно, вы захотите добавить дополнительные возможности отладки:
- возможность аннулировать итератор
- возможность проверки диапазона
- проверка контейнера (т. Е. Проверка при сравнении двух итераторов, что они ссылаются на один и тот же контейнер для начала)
Но это тонкости, и для начала, это немного сложнее.
Обратите внимание также Boost.Iterator , который помогает с кодом пластины котла.
РЕДАКТИРОВАТЬ: (сгруппированы обновления 1 и 2)
В вашем случае хорошо, если ваш итератор - просто int, вам больше не нужно. На самом деле для сильного перечисления вам даже не нужен итератор, вам просто нужны оператор ++ и оператор--:)
Смысл ссылки на контейнер обычно заключается в реализации этих операторов ++ и -. Но из вашего элемента достаточно иметь значение int (при условии, что оно достаточно большое) и способ добраться до предыдущего и следующего значений.
Было бы проще, если бы у вас был статический вектор, вы могли бы просто повторно использовать векторный итератор.