STL Итераторы Первое знакомство и долой сомнения Итератор — это не указатель

Первое, с чем я знакомился начав изучать STL был вектор (vector). При изучении и описании векторов столкнулся с некоторыми новыми понятиями. Первое такое понятие итератор (iterator). Применить и понять смысл применения итератора в векторе мне было нетрудно, но наверное найдутся такие люди, которым что-то очевидное мне, может быть совсем не таким очевидным.

Первый простой пример — это перебор элементов массива с помощью итераторов.

Здесь код совсем маленький и не должен вызывать вопросов. Согласно стандарту, каждый контейнер должен содержать такие методы как begin и end. Что такое begin и end должно быть понятно. Это как указатели на первый и последний элементы контейнера
vector::begin() — Возвращает итератор на первый элемент вектора
vector::end() — Возвращает итератор на последний элемент вектора
(вот этот вверху vector имя условное, у нас в примере было не vector, а v)

Небольшое пояснение по последнему элементу вектора. Последний элемент вектора — это не тот элемент, который мы последним запихнули в него, не последний элемент последовательности, а последний элемент вектора. Последний элемент вектора идет сразу за последним элементом последовательности, хранящейся в векторе. Нагляднее всего это демонстрирует простой пример.

Сейчас вернемся к коду до пояснения. Может возникнуть вопрос: "Зачем нужна та строчка со вторым циклом". Эта строчка знакома тем, кто изучал массивы и указатели. Благодаря арифметике указателей, перебор элементов массива можно осуществлять прибавлением к указателю целого значения (или с помощью вычитания). Показано это только для того, чтобы продемонстрировать очень большую схожесть итератора с указателем. Такая большая схожесть может сильно запутать, но путаться не надо. Итератор указателем не является.
Я поясню не профессионально, но и не ошибочно

Чтобы уяснить некоторую разницу между итератором и указателем в первую очередь нужно пройтись по определениям и предназначениям первого и второго

  • Указатель — это переменная, обозначающая адрес памяти. Предназначен указатель для того, чтоб мы могли напрямую обращаться по некоторому адресу памяти к объекту, который по этому адресу лежит
  • Итератор — объект, позволяющий программисту перебирать все элементы коллекции без учёта особенностей её реализации. Предназначен итератор исключительно для последовательного доступа к элементам

Что такое последовательный доступ легче понять тем, кто затрагивал динамическое программирование и стеки. При последовательном доступе перемещение происходит элемент за элементом, а при прямом указали номер элемента и мы на месте.

В случае с вектором итератор иногда является указателем, но не всегда, с остальными стандартными контейнерами нет. Пример работы с итератором как с указателем

Итераторы подчиняются принципу чистой абстракции, то есть любой объект, который ведет себя как итератор, является итератором, поэтому про указатель иногда (не всегда) можно сказать, что он (указатель) является итератором. Чтоб он был итератором, он должен вести себя как итератор.

В С++ различают различные типы итераторов:

  • Однонаправленные итераторы
  • Обратные итераторы (реверсные)
  • Двунаправленные итераторы
  • Итераторы произвольного доступа
  • Итераторы ввода и Итераторы вывода
  • Пользователи могут создавать собственные типы итераторов, определяя подклассы на основе стандартного шаблона классов std::iterator

Обычно итераторы используется парами. Первый обозначает начало перебора, второй обозначает, что дальше перебирать нечего и нужно остановиться. Это должно было быть понятно по приведенным вверху примерам.
У кого-то могут зарождаться сомнения, которые я только что так старался убить. Сомнения по поводу указателей и итераторов. Итераторы произвольного доступа сеют семя этих сомнений (вот у меня сейчас сеют). Но итераторы произвольного доступа — это такие специальные двунаправленные итераторы. Для меня сочетание двунаправленный указатель звучит немного забавно, вы о таком слышали? Нет и вряд ли услышите)

Синтаксис стандартных итераторов сделан похожим на обычные указатели языка Си, где операторы * и -> используются для указания элемента, на который указывает итератор, а такие арифметические операторы указателя, как ++, используются для перехода итератора к следующему элементу.

  • Главное предназначение итераторов заключается в предоставлении возможности пользователю обращаться к любому элементу контейнера при сокрытии внутренней структуры контейнера от пользователя. Это позволяет контейнеру хранить элементы любым способом при допустимости работы пользователя с ним как с простой последовательностью или списком. Проектирование класса итератора обычно тесно связано с соответствующим классом контейнера. Обычно контейнер предоставляет методы создания итераторов

Как указатель не всегда является итератором, так и итератор не всегда является указателем
Код С++ Поверь или умри!!

Такое простое практическое доказательство того, что итератор не является указателем.

  • Итератор является «умным» указателем на элемент контейнера. В отличие от обычного указателя он помнит полный тип данных на который ссылается – с учётом типа контейнера, к элементу которого производится обращение.
Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

6 комментариев: STL Итераторы Первое знакомство и долой сомнения Итератор — это не указатель

  • Arete говорит:

    «vector::end() – Возвращает итератор на последний элемент вектора»
    Метод end() указывает не НА последний елемент последовательности, а ЗА него.




    0



    0
    • admin говорит:

      Returns an iterator referring to the past the end element in the vector container.
      Возвращает итератор, ссылаясь на последний конечный элемент в векторе контейнер




      0



      0
      • admin говорит:

        Чтобы было понятнее, последний не для нас как для людей, а последний в строении вектора. Этот последний в строении вектора элемент для нас как для людей последующий за конечным и есть.

        Я подправлю это в статье




        0



        0
  • Cast говорит:

    пример2 -зыбыли

    строка 8 :

    строка12:




    0



    0
  • asd говорит:

    разница между итератором и указателем — на самом деле в том, что первый может указывать на абсолютно любой участок памяти, а второй — строго на начало конкретного элемента, по сути, превращаясь в индекс. И второе, отдельный тип iterator — в первую очередь нужен самому STL, а именно, компилятору, чтоб правильно выбрать прототип шаблонной функции и, соответственно, саму функцию.

     

    и последнее, насчёт «последнего элемента» — на примере вектора:

    struct VectorAllocator

    {

    int allocator.dummy;              //это поле занимает dword в памяти но, реально используется только первый байт

    int _First;             //первый элемент

    int _Last;             //последний элемент

    int _End;             //аналог поля «_Cap» в basicstring

    } // не силён в «этих ваших» — поэтому правильность синтаксиса при описании структуру может хромать. Но это 100% рабочий вариант

     

    т.е. другими словами, поле _End — это максимальный размер вектора при превышении которого произойдёт его реаллокация. Т.е. создастся новый вектор большего размера, старый вектор скопируется в новый, а старый — удалится. Отчасти из-за этого безопаснее использовать итераторы, а не такой «прямой» доступ «в лоб», как указатели. Т.е. это своего рода аналог хендлов (в части, касающейся доступа к элементам)

    Автор сайта отвечает:
    Насчет последнего вообще ничего непонятно. Да и скорее всего неправильно.
    А насчет первого, может и правильно, но трактовка нечетко выражена, возможно воспринимать по-всякому, вплоть до абсолютно противоположного.
    Этот блог новички читают, желательно пояснять доступным для них языком без использования языкового сленга и непонятных аналогов.




    0



    0
  • asd говорит:

    админ — не адекват.  ладно честно признаётся, что весьма не далёкий в с++ — так ещё и дельный коммент затёр. ну… надеюсь, что хоть не остальные так он его прочёл и принял к сведению)))

    удачи тебе, с твоим «бложиком».

    Автор сайта отвечает:
    Чего я тебе затёр?




    0



    0

Добавить комментарий

Ваш e-mail не будет опубликован.

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/robin-nikson/sozdaem-dinamicheskie-veb-sayty-s-pomoschu-php-mysql-javascript-i-css-2/?lfrom=15589587
Яндекс.Метрика
НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

Демотиватор никогда не сдаваться

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок