Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Использование итераторов С++ с массивами

#cpp #итераторы


Возможно, кто-либо может объяснить итераторы и их использование с массивами, или
же дать соответствующую литературу по этой теме?

Т.к. я читал по разным книгам о итераторах, но там идет речь о использовании их совместно
с STL и т.п., а как самому написать - особо такого не написано... Насколько я понял,
то они нужны, чтобы перебирать и т.п. элементы массива. Я правда не знаю смысл в этом,
если вроде бы можно и непосредственно обращаться, ну да ладно, не важно.
Т.е. нужно создать вложенный класс внутри класса, где будет содержаться, скажем, массив?

Если я понял, то в конце концов, когда он написан, то, к примеру, для цикла выведения
массива будет такой код:

for(start = Iterator.begin(); start != end; start++)
{
    cout << *start;
}


Или я что-то путаю?

P.S.: А ещё, если у кого есть книги, где об этом говорится, статьи, то пожалуйста
и их напишите тоже сюда.



class Array
{
private:
    int* p;
public:
    class Iterator
    {
        public:
        Iterator()  
        {
            p = nullptr;
        }
        Iterator(int *pv)
        {
            p = pv;
        }
        int operator *() const
        {
            return *p;
        }
        Iterator operator ++(int)
        {
            int *temp = p;
            return ++temp;
        }
    };

    Array();
    ~Array();
int& operator[] ();
    Iterator begin()
    {
        return Iterator(buffer_)
    }
int* buffer_;

void partial_sort(Array::Iterator start, Iterator end)
{
    start
}


Вот как понять что-то вроде этого... Точнее говоря это наброски, они не совсем мои..
Вот мне нужно сделать примерно такое же, только работающее..



Если говорить поконкретнее насчёт того, что не понимаю...
Вот класс итератор вложенный, в нем какое поле должно быть ?
При перегрузке Iterator operator ++(int) это он типо должен будет перебирать элементы
массива же, да?
А если я хочу перегрузить ==?
Я пробовал писать что-то вроде:  

Iterator operator==(Iterator it1, Iterator it2)


Чтобы сравнивать их на равенство, но не получается - ошибка "много аргументов".
ДА и ещё не до конца понимаю как его реализовать..
Т.е. допустим функции вывода, сортировок вместо того, чтобы передавать массив и его
длину мне нужно будет передавать 2 итератора, верно? Один из них указывает на начало,
другой на конец, да?
А вывод массива в таком случае выглядел бы с итераторами так:

for(start ???; start != end; start++)
  cout << *start;

    


Ответы

Ответ 1



Вот, собственно, пример итератора. Этот код вырезан из SGI STL, почищен от всяких подробностей, чтобы оставить суть. Тут можно посмотреть что и как в итераторах должно быть в принципе: #include // нужен только лишь для типа std::size_t class iterator { protected: int* p; public: explicit iterator(int* __i) : p(__i) { } // Forward iterator requirements const int& operator*() const { return *p; } int& operator*() { return *p; } int* operator->() const { return p; } // prefix increment (++it) iterator& operator++() { ++p; return *this; } // postfix increment (it++) iterator operator++(int) { return iterator(p++); } // Bidirectional iterator requirements // prefix decrement (--it) iterator& operator--() { --p; return *this; } // postfix decrement (it--) iterator operator--(int) { return iterator(p--); } // Random access iterator requirements const int& operator[](const std::size_t& __n) const { return p[__n]; } int& operator[](const std::size_t& __n) { return p[__n]; } iterator& operator+=(const std::size_t& __n) { p += __n; return *this; } iterator operator+(const std::size_t& __n) const { return iterator(p + __n); } iterator& operator-=(const std::size_t& __n) { p -= __n; return *this; } iterator operator-(const std::size_t& __n) const { return iterator(p - __n); } int* base() const { return p; } }; // Forward iterator requirements inline bool operator==(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() == __rhs.base(); } inline bool operator!=(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() != __rhs.base(); } // Random access iterator requirements inline bool operator<(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() < __rhs.base(); } inline bool operator>(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() > __rhs.base(); } inline bool operator<=(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() <= __rhs.base(); } inline bool operator>=(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() >= __rhs.base(); } inline std::size_t operator-(const iterator& __lhs, const iterator& __rhs) { return __lhs.base() - __rhs.base(); } inline iterator operator+( std::size_t __n, const iterator& __i) { return iterator(__i.base() + __n); } Обратите внимание на explicit конструктор, на то какие операторы перегружены для того, чтобы итератор удовлетворял концепциям: forward iterator random access iterator bidirectional iterator

Ответ 2



Итераторы призваны предоставлять доступ к членам контейнеров, они могут быть использованы способом, похожим на манипуляции указателями. Например, можно использовать итератор для прохода по всем элементам вектора. Есть несколько разных типов итераторов. Каждый класс контейнеров связан с типом итератора, и каждый из алгоритмов STL использует определенный тип итератора. Например, векторы связаны с итераторами с произвольным доступом, значит, они могут использовать алгоритмы, требующие произвольного доступа. Так как итераторы с произвольным доступом включают в себя все свойства других итераторов, то векторы также могут использовать алгоритмы, написанные для других итераторов. Код в примере создает итератор и использует его в векторе: vector the_vector; vector::iterator the_iterator; for( int i=0; i < 10; i++ ) the_vector.push_back(i); int total = 0; the_iterator = the_vector.begin(); while( the_iterator != the_vector.end() ) { total += *the_iterator; ++the_iterator; } cout << "Итого=" << total << endl; Получить доступ к элементам контейнера можно путем разыменования итератора.

Ответ 3



Массив - это конкретная форма хранения данных. Отличается тем, что у нас есть числовой индекс у каждого элемента. Причем этот индекс уникален. Обычно эти индексы представляют собой целые числа от некоего минимального до некоего максимального с каким-то фиксированным шагом. int a[100]; for (int i = 0; i < 100; i++) { std::cout<

Ответ 4



В принципе итератор, это просто расширенная концепция указателя и все алгоритмы STL, работающие с итераторами должны работать и с указателями напрямую: #include #include void go( int value ) { printf("%d\n", value); } int main() { int a[5] = { 0, 1, 2, 3, 4 }; std::for_each( &a[0], &a[5], &go ); return 0; }

Ответ 5



class MyIterator; class MyArray{ public: MyIterator* Iterate(); // возвращает пассивный итератор, index в 0. bool More(MyIterator*); // true если еще есть элементы, иначе - false int Next(MyIterator*); // возвратим текущий элемент массива, index++ ... }; class MyIterator { int index; // здесь мы будем хранить номер текущего элемента // для конкретного итератора, т.к. итераторов мы можем завести много. ... } MyArray* collection = new MyArray(100);// сделаем-ка массив на 100 элементов, // для этого конструктор коллекции должен принимать кол-во элементов ... MyIterator* iter = collection->Iterate(); //сделаем итератор ... while (collection->More(iter)) // пока еще есть элементы std::cout<Next(iter)<

Ответ 6



Есть классная книга: "С++. Методики программирования Шилдта". там примерно половина посвящена итераторам

Комментариев нет:

Отправить комментарий