Absurd писал(а):Итератор это разновидность смарт-указателя.
В корне не согласен. Итераторы и смарт-поинтеры похожи только тем, что прячут в себе указатель. Но по ни по функциональному предназначению, ни по имплементационым требованиям они вообще не сравнимы.
Итераторы используются лишь как средство для перебора элементов контейнера. То есть у итератора должна быть возможность перехода к предыдущему/следующему элементу (для random acceess ещё и средства произвольного доступа) и возможность получить данные, на которые итератор указывает. Если отбросить пару дополнительных примочек (таких, как сравнение итераторов), то на этом их функциональность заканчивается. Итераторы никак не владеют данными, на которые указывают и, тем более, не могут их удалять!
Смарт-поинтеры предназначены для хранения указателя на память и
управления этой памятью. Здесь идёт акцент на владение (с помощью разных стратегий - экслюзивное, разделяемое, слабое) и на своевременное удаление. Но, в противовес итераторам, смарт-поинтеры не имеют возможность перейти к предыдущему/следующему указателю.
Absurd писал(а):У смарт-указателей operator bool() обычно перегружают, чтобы работало такое.
В текущей реализации STL у итератора нет оператора bool. И, кстати, это объясняется достаточно просто. Если для итераторов одних контейнеров, таких, как список, нулевое значение внутреннего указателя может сигнализировать об окончании перебора, то для других, скажем, вектора, окончание перебора вообще не может быть определено без дополнительной информации, так как итерирование, по факту, идёт по диапазону адресов, и где заканчивается этот диапазон "знает" только контейнер.
Сионист писал(а):И каким же образом могут быть универсальны внутренности иттератора? Их классы не просто так являются членами классов контейнеров вместо единого класса иттератора "вперёд" и одного реверсивного.
Речь идёт об универсальности интерфейса, а не внутренностей. Дело в том, что все алгоритмы реализованы в виде внешних шаблонных функций, так что они не привязаны к типу итератора. Можно передать как обычные поинтеры, так и объекты своего класса. Главное, чтоб был доступен весь набор необходимых операторов, чтобы компилятор смог сгенерировать инстанс функции для этого типа.
Сионист писал(а):Ну-ка переберите список указателем, юзая простой инкремент вместо p=p->Next. Они ведь не знают не только о конце контейнера, но и о фактическом размещении следующего элемента.
Ну почему ты любую идею пытаешь извратить? Смотри, давай по порядку.
В языке C был один единственный встроенный контейнер. Знаешь такой? Это C-массив. Элементы массива можно было перебрать, используя указатель. Например вот так:
Код: Выделить всё
const int N = 3;
int arr[N] = {1, 2, 3};
...
int* begin = arr;
int* end = arr + N;
for (int* p = begin; p != end; ++p)
{
printf("%d ", *p);
}
Эта идея достаточно проста, поэтому, надеюсь, понята.
Создавая язык С++, разработчики сделали следующий шаг и абстрагировали предыдущий подход. Они создали билиотеку STL, наполнили её классами-контейнерами и ввели понятие итератора.
-
А что же такое итератор, - спросили их программисты?
-
Итератор - это такой объект, которым можно перебрать элементы контейнера, - ответили разработчики. -
Причём у этого итератора вы можете использовать ровно такой же набор операторов, какой использовали у поинтера, когда перебирали С-массив. Этим мы добились того, что даже для С-программистов код остался прозрачным и ожидаемым. А ещё получили возможность, одинаково хорошо применять все фишки из нашего нового <algorithm> как для встроенных итераторов (читайте "поинтеров"), так и для пользовательских. Единообразность и ожидаемость - наше всё.
И так, ещё раз от просто к сложному. С-массив -> поинтер. Пользовательский контейнер -> итератор. Идея понятна?
Сионист, ещё раз хочу подчеркнуть, что всё, что я написал выше, касается исключительно STL. Так что, если ты собираешься делать свой итератор, ты волен заимплементить его так, как посчитаешь нужным. Я лишь высказываю резонные мысли и ставлю в пример достаточно продуманную готовую библиотеку, давая тем самым тебе пищу для размышлений.