Using C++ iterators with arrays

Perhaps someone can explain iterators and their use with arrays, or provide relevant literature on the topic?

Because I read about iterators in various books, but they talk about using them in conjunction with STL, etc., and how to write it yourself - it is not particularly written... As far as I understand, they are needed to iterate through the array elements, etc. I really do not know the meaning of this, if it seems that you can directly apply, well, okay, do not important. That is, you need to create a nested class inside the class, which will contain, say, an array?

If I understand, then in the end, when it is written, then, for example, for the array output loop, there will be this code:

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

Or am I confusing something?

P.S.: And also, if anyone has books where this is said, articles, then please write them here too.


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
}

Here's how to understand something like this... More precisely, these are sketches, they are not really mine.. Here's what I need make something similar, only working..


To be more specific about what I don't understand ...
Here is the iterator nested class, what field should it contain ?
When overloading Iterator operator ++(int) , it will have to sort through the elements of the array, right?
And if I want to overload ==?
I tried writing something like:

Iterator operator==(Iterator it1, Iterator it2)

To compare them for equality, but it doesn't work - the "many arguments"error.
Yes, and I still don't fully understand how it is to realize..
That is, let's say the output functions, sorts, instead of passing an array and its length, I will need to pass 2 iterators, right? One of them points to the beginning, the other to the end, right?
And the output of the array in this case would look like this with iterators:

for(start ???; start != end; start++)
  cout << *start;
Author: Abyx, 2011-05-14

6 answers

Here, in fact, is an example of an iterator. This code is cut from the SGI STL, cleaned of all the details to leave the essence. Here you can see what and how the iterators should be in principle:

#include <cstddef> // нужен только лишь для типа 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); }

Pay attention to the explicit constructor, which operators are overloaded in order for the iterator to satisfy the concepts:

  • forward iterator
  • random access iterator
  • bidirectional iterator
 7
Author: Ander, 2011-05-26 12:42:56

Iterators are designed to provide access to container members, and they can be used in a way similar to pointer manipulation. For example, you can use an iterator to traverse all the elements of a vector. There are several different types of iterators.

Each container class is associated with an iterator type, and each of the STL algorithms uses a specific iterator type.

For example, vectors are associated with random-access iterators, so they can use algorithms that require random access. Since random-access iterators include all the properties of other iterators, vectors can also use algorithms written for other iterators.

The code in the example creates an iterator and uses it in the vector:

    vector<int> the_vector;
    vector<int>::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;

You can access the container elements by dereferencing the iterator.

 2
Author: megacoder, 2011-05-14 19:45:11

An array is a specific form of data storage. It differs in that we have a numeric index for each element. Moreover, this index is unique. Usually these indexes are integers from some minimum to some maximum with some fixed increment.

int a[100];

for (int i = 0; i < 100; i++)
{
    std::cout<<a[i]; //вывести на экран i-тый элемент массива
}

When the standard array starts to fail, you can make a special class that will overload the [] operator and will look like an array. But at the same time, the internal structure can be, for example, a linked list or something even more tricky. It all depends on the tasks.

Next, no one bothers to overload this operator so that it accepts, for example, a string. This is useful for creating dictionary-type data structures. The presence of numerical indexes is no longer necessary.

But at the same time, in any case, the problem arises of ensuring the possibility of element-by-element iteration of the elements of such an "array". That's where the iterator comes in. This is some kind of thing that knows how iterate through the elements. Again, we, as a user, do not care about the internal implementation. And from the developer's point of view, we can make it optimized for a specific task. There are different types of iterators: passive, active - depending on how they relate to the class for which they are used. This is all well written in Jeff Alger's book " C++.Programmer's Library", ed. Peter.

PS: as an array type in fresh compilers, I would recommend using template type std:: array.

 2
Author: gecube, 2011-05-14 21:17:31

Basically, an iterator is just an extended pointer concept, and all STL algorithms that work with iterators should work with pointers directly as well.:

#include <stdio.h>
#include <algorithm>

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;
}
 2
Author: Ander, 2011-05-14 23:14:20
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<<collection->Next(iter)<<std::endl; // выведем текущий элемент.

It's crooked, but it sounds like it.

 1
Author: gecube, 2011-05-14 21:14:29

There is a cool book: "C++. Schildt programming techniques". there's about half devoted to iterators

 -2
Author: Pavel S. Zaitsau, 2011-05-16 20:53:58