Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Итератор

13K
16 декабря 2005 года
Shida
5 / / 20.10.2005
Люди, помогите! Please:)))
Объясните руским языком, что такое итератор и с чем его едят!!!
398
16 декабря 2005 года
Alexandoros
630 / / 21.10.2005
Итератор это объект для обхода в цикле сложных структур даных таких как списки, очередя, деревья, графы.

Допустим есть у тебя список
Код:
std::list<int> mylist;

std::list<int>::iterator i;

//заполняем список

mylist.push_back(1);
mylist.push_back(2);
mylist.push_back(3);

// теперь бы нада в цикле обработать этот списочек.

for(i = mylist.begin(); i != mylist.end(); i++)
    do_something(*i);  // i - итератор
                       // *i - элемент списка типа int


Для списка пример не очень актуален, можно ведь написать и mylist.next() (или чтото в этом роде), но вот для тех же бинарных деревьев/графов такой подход не покатит, - нужен итератор.
3
16 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by Alexandoros
Для списка пример не очень актуален, можно ведь написать и mylist.next() (или чтото в этом роде)


Это не совсем так, т.к. итератор используется в стандартных алгоритмах (#include <algorithm>), поэтому для списка, как одного из контейнеров, это весьма актуально.

И ещё, для итератора уже имеет смысл писать ++i, а не i++.

398
16 декабря 2005 года
Alexandoros
630 / / 21.10.2005
Цитата:
Originally posted by Green

И ещё, для итератора уже имеет смысл писать ++i, а не i++.


Вот тут можно б и по-подробнее. В с++ есть разделение на перегрузку ++i и i++. Но какая разница итератору???? ++і и i++ ведь выполняют одинаковые действия.

2.4K
16 декабря 2005 года
dinasok51
219 / / 12.11.2005
Итератор это аналог указателя - указывает на объект внутри коллекции ( map, set, list, vector и др.)
или на конец коллекции.
Итератор обладает некоторыми свойствами указателя
*it возвращает объект

Но
++it переставляет указатель на следующий объект коллекции(если он имеется)

--it переставляет указатель на предыдущий объект коллекции(если он имеется)


.begin() - указатель на первый объект
.end() - указатель на КОНЕЦ коллекции,
а не последний объект!!!

В дополнение к примеру Alexandoros'а
std::map<int> MyMap;
std::map<int>::const_iterator it;

// Где-то заполнен map


// Поиск в map
if ( (it= MyMap.find(20)) != MyMap.end() )
{
// нашел; it указывает на то что содержит 20

}
3
16 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51

Итератор обладает некоторыми свойствами указателя
*it возвращает объект


Если быть точным, то не объект, а ссылку на существующий объект, а в особом случае (bool) ссылку на прокси-объект.

Цитата:
Originally posted by Alexandoros

Вот тут можно б и по-подробнее. В с++ есть разделение на перегрузку ++i и i++. Но какая разница итератору???? ++і и i++ ведь выполняют одинаковые действия.


Попробуй сам ответить на вопрос:
если они выполняют "одинаковые действия", то зачем тогда в С++ два оператора: префиксный (++i) и постфиксный (i++) ?

Ответ прост.

2.4K
16 декабря 2005 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Green
Если быть точным, то не объект, а ссылку на существующий объект, а в особом случае (bool) ссылку на прокси-объект.


На программном уровне внутреннее устройство STL слава аллаху не видна!
и если уж написал

MyType MyVar = *it;

то всегда получишь содержимое того чего надо, а не неких промежуточных инстанций, зависящих от конкретной реализации STL( Если итератор инициализирован )

Цитата:
Originally posted by Green

Попробуй сам ответить на вопрос:
если они выполняют "одинаковые действия", то зачем тогда в С++ два оператора: префиксный (++i) и постфиксный (i++) ?

Ответ прост.



Ответ не так уж прост
В постфиксном операторе создается временный объект со временем жизни всего следующего оператора.
Создание и разрушение съедают ресурсы и именно поэтому не рекомендуется использовать постфиксные операторы

3
16 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51
На программном уровне внутреннее устройство STL слава аллаху не видна!
и если уж написал

MyType MyVar = *it;

то всегда получишь содержимое того чего надо, а не неких промежуточных инстанций,


А если написал

MyType& MyVar = *it;

:)

Цитата:
Originally posted by dinasok51
зависящих от конкретной реализации STL


Ситуация с bool - это не "конкретная реализация", а стандартная вещь.

Цитата:
Originally posted by dinasok51

Ответ не так уж прост


Ну уж не сложен, если уместился в двух строчках... :)

2.4K
16 декабря 2005 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Green

Ситуация с bool - это не "конкретная реализация", а стандартная вещь.



Цитатку из стандарта можно? Для убедительности.

Цитата:
Originally posted by Green

Ну уж не сложен, если уместился в двух строчках...



Если знаешь ответ, или делаешь вид что знаешь

3
16 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51
Цитатку из стандарта можно? Для убедительности.


Да пожалуйста:
http://ftp.csci.csusb.edu/dick/c++std/cd2/lib-containers.html#lib.vector.bool

Цитата:

23.2.5 Class vector<bool>

1 To optimize space allocation, a specialization of vector for bool elements is provided:
<skip>

2 reference is a class that simulates the behavior of references of a single bit in vector<bool>.

2.4K
16 декабря 2005 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Green
Да пожалуйста:
http://ftp.csci.csusb.edu/dick/c++std/cd2/lib-containers.html#lib.vector.bool



Классно, но не по делу

Цитата:
Originally posted by Green
в особом случае (bool) ссылку на прокси-объект.



Хотелось цитату, подтверждающую что оператор *итератор возвращает "в особом случае (bool) ссылку на прокси-объект", что и является сутью нашего обсуждения.

3
17 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51
Классно, но не по делу

Хотелось цитату, подтверждающую что оператор *итератор возвращает "в особом случае (bool) ссылку на прокси-объект", что и является сутью нашего обсуждения.


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

Чтож, придется разжевывать...

Для оптимизации по памяти существует частная специализация vector

Цитата:

23.2.5 Class vector<bool>
To optimize space allocation, a specialization of vector for bool elements is provided:


расположение элементов в vector<bool> хотя и последовательное, но отличается от стандартного

Цитата:

23.2.4.1
....
The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().


Т.о. тип bool представлен в контейнере одним битом, что исключает возможность прямой непосредственной адресации к отдельному элементу, как к типу bool. Поэтому введен прокси-класс reference

Цитата:

23.2.5.2
reference is a class that simulates the behavior of references of a single bit in vector<bool>.


Итератор вектора является как минимум forward итератором (23.1.1.5, 23.1.9), поэтому должен не просто возвращать значение элемента при разыменовании, а давать доступ к элементу контейнера (24.1.3). Но т.к. вернуть ссылку на объект типа bool из vector<bool> невозможно, возвращается прокси-обект класса reference.

Надеюсь, теперь моё мнение понятно?
Хотелось бы услышать твоё объяснение своей позиции.

2.4K
17 декабря 2005 года
dinasok51
219 / / 12.11.2005
Я отвечал на вопрос уважаемого Shida и считаю свой ответ достаточно корректным

Реализация всех особых случаев скрыта от программы (здесь можно было бы прочесть лекцию об инкапсуляции). Детали этой реализации в большинстве случаев не неинтересны
А для ответа на вопрос Shida IMHO просто вредны, тк затуманивают общую картину

Я уверждаю:
В конструкции

MyType MyVar = *Iterator

всегда получаешь значение того что в контейнер положил, и ничего другого и никакие разыменования тут не нужны.
Как и смайлики.

А теперь Green по поводу нашей дискуссии
Я не просил комментарии, я просил цитату из стандарта, на кот ты ссылаешься,
подтверждающую твое высказывание, что
*Iterator возвращает ссылку на то, что ты наз. прокси

Так что это опять не ответ на мой вопрос.

И последнее:
Замечания по поводу разжевывания и пр. оскорбительны. Могу тебя заверить: по части хамства у меня зачет с отличием, но на форуме никогда не буду опускаться до упражнений в оном.
3
17 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51

Я уверждаю:
В конструкции

MyType MyVar = *Iterator

[COLOR=red]всегда получаешь значение[/COLOR] того что в контейнер положил, и ничего другого и [COLOR=red]никакие разыменования тут не нужны[/COLOR].
Как и смайлики.


Во-первых, *Iterator, т.е. operator* - это и есть унарный оператор разыменования. Так что он в твоем примере все же нужен.

Во-вторых, получишь или нет зависит от того, что скрывается за MyType. При
typedef bool& MyType
получишь не значение, а ошибку компиляции.

Цитата:
Originally posted by dinasok51

А теперь Green по поводу нашей дискуссии
Я не просил комментарии, я просил цитату из стандарта, на кот ты ссылаешься,
подтверждающую твое высказывание, что
*Iterator возвращает ссылку на то, что ты наз. прокси

Так что это опять не ответ на мой вопрос.


Если ты придираешься к тому, что я изначально написал "возвращает ссылку на прокси-объект", а не "возвращает прокси-объект", то да, я оговорился.
Но здесь было много неточностей, например, что std::map имеет два параметра шаблона, а не один...

Если же это не вышеобозначенная придирка, а мнение, что возвращение прокси-объекта при разыменовании для vector<bool> - это случай конкретной реализации, то попробуй доказать обратное цитатой из стандарта.
А то похоже на глупое упрямство с твоей стороны.

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

А от тебя пока никаких доказательств не услышал.

Цитата:
Originally posted by dinasok51

И последнее:
Замечания по поводу разжевывания и пр. оскорбительны. Могу тебя заверить: по части хамства у меня зачет с отличием, но на форуме никогда не буду опускаться до упражнений в оном.


Ну уж прости за резкость.
А мне вот не нравится, когда опонент в категоричной форме требует доказательств сам никак не аргументируя свою позицию.

2.4K
18 декабря 2005 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Green
Во-первых, *Iterator, т.е. operator* - это и есть унарный оператор разыменования. Так что он в твоем примере все же нужен.



operator* разыменовыет итератор, кто бы спорил.
Вопрос во что?

Если *It возвращает прокси, то требуется еще и преобразование к нужному типу: что-то вроде (bool)(*It). А это не нужно. Это к вопросу об инкапсуляции.


Цитата:
Originally posted by Green

Во-вторых, получишь или нет зависит от того, что скрывается за MyType. При
typedef bool& MyType
получишь не значение, а ошибку компиляции.



Зачем же так плохо думать об оппоненте?
Не буду же я ваять list<bool&>

Цитата:
Originally posted by Green
Если ты придираешься к тому, что я изначально написал "возвращает ссылку на прокси-объект", а не "возвращает прокси-объект", то да, я оговорился.
Но здесь было много неточностей, например, что std::map имеет два параметра шаблона, а не один...


Каюсь, грешен, имел в виду set а вышло map

Цитата:
Originally posted by Green
Если же это не вышеобозначенная придирка, а мнение, что возвращение прокси-объекта при разыменовании для vector<bool> - это случай конкретной реализации, то попробуй доказать обратное цитатой из стандарта.


Я не ссылался на стандарт.

Цитата:
Originally posted by Green
А то похоже на глупое упрямство с твоей стороны.


Все равно не буду упражняться

Цитата:
Originally posted by Green
Я кажется логично объяснил свою позицию на конкретных взаимосвязанных пунктах стандарта, которые четко (хотя и не явно) определяют, положение вещей.


Обяснений было много, но ни в нигде не был упомянут оператор*, как он живет в list<bool>


Цитата:
Originally posted by Green
А от тебя пока никаких доказательств не услышал.


А что я должен доказать?

Цитата:
Originally posted by Green

Ну уж прости за резкость.
А мне вот не нравится, когда опонент в категоричной форме требует доказательств сам никак не аргументируя свою позицию.



Ты сослался на стандарт, я посмотрел его, но не нашел подтверждения твоим словам. Во я и попросил тебя и совсем ненавязчиво.

Я предлагаю следующее:
Ты пишешь 3-5-7 строк программного кода,
(ничего не переопределяя в STL ) и показываешь
как *Iterator возвращает прокси.
И чтоб откомпилировалось!

Это будет самым лучшим доказательством твоей правоты.

А на дискуссию на уровне "А ты кто такой" время тратить не желаю.

3
18 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51
operator* разыменовыет итератор, кто бы спорил.
Вопрос во что?


Согласно стандарту (24.1.1.2 Table 72) в "convertible to T", а для контейнеров это T& (24.1.3 Table 74).

Цитата:
Originally posted by dinasok51

Если *It возвращает прокси, то требуется еще и преобразование к нужному типу: что-то вроде (bool)(*It). А это не нужно. Это к вопросу об инкапсуляции.


Инкапсуляция тут не при чем. Здесь имеет место неявное преобразование типов.

Цитата:
Originally posted by dinasok51

Обяснений было много, но ни в нигде не был упомянут оператор*, как он живет в list<bool>


Я говорил про vector<bool> и vector<bool>::iterator. Ты говорил, что итератор возвращает объект, я поправил, что итератор возвращает ссылку на объект и в исключительном случае возвращает прокси-объект.

Цитата:
Originally posted by dinasok51

А что я должен доказать?


То на чем ты настаиваешь. Видимо то, что разыменование итератора возвращает объект хранимый в контейнере и это происходит во всех случаях, даже для vector<bool>.
Или я тебя неправильно понял?
В любом случае, если ты считаешь, что я неправ, то у тебя есть правильный вариант. Вот его опиши и обоснуй.

Что бы не было дальнейших непониманий, под "возвращает объект" я понимаю
T func();
под "возвращает ссылку на объект" я понимаю
T& func();

Цитата:
Originally posted by dinasok51

Я предлагаю следующее:
Ты пишешь 3-5-7 строк программного кода,
(ничего не переопределяя в STL ) и показываешь
как *Iterator возвращает прокси.
И чтоб откомпилировалось!

Это будет самым лучшим доказательством твоей правоты.


Вариант 1

 
Код:
vector<bool> container(1);
vector<bool>::iterator it = container.begin();

// доказательство номер 1
// bool& b = *it; // эта строчка не скомпилируется

// доказательство номер 2
// reference - это прокси-объект
vector<bool>::reference ref = *it;
ref.flip();  // у этого прокси есть метод flip(), а у bool он есть?

Вариант 2
 
Код:
template<class Type>
void func(Type arg) {
    class A {
        Type t[];
    };
}

vector<bool>::iterator it;
func(*it);

Этот код скомпилируется (такое условие ты выдвинул), но с предупреждением. Посмотри на тип упоминаемый в предупреждении и ты увидишь, что в func передается совсем не bool. Это прокси, который в различных реализациях может называться по-разному, но всегда носит второе имя reference.
13K
19 декабря 2005 года
Shida
5 / / 20.10.2005
[QUOTE]Originally posted by Alexandoros
Итератор это объект для обхода в цикле сложных структур даных таких как списки, очередя, деревья, графы.

:roll: Доброе время суток:)А можно ли использовать итераторы с динамическими массивами? У меня есть 3-х мерный динамический массив и мне нужно работу с ним представить, как работу с итератором.
2.4K
19 декабря 2005 года
dinasok51
219 / / 12.11.2005
Green

1. Я утверждал уже 2 раза и уверждаю в 3 раз:
В конструкции

MyType MyVar = *Iterator

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

Вопрос с Type& мы не рассматриваем, также как и массивы ссылок.

2. И я утверждал, что возвращаемое значение в *iterator зависит от реализации STL, т.к. я с этим сталкивался.

Ничего другого я не утверждал, я задавал вопросы и не был удовлетворен некоторыми ответами.

3. По поводу доказательств и примеров

3.1 Мелкие очепятки не рассматриваем
3.2 Якобы "доказательство номер 1"
// bool& b = *it;
Мы уже договаривались, не использовать аргументы, оскорбляющие умственные способности оппонента.

3.3 По существу:

VS 2003 компилирует все твои примеры.
VS6 SP6 образца 2004 года твое док-во номер 1 не компилирует.

Каждая конкретная РЕАЛИЗАЦИЯ STL работает несколько иначе, несмотря на наличие стандарта.
Во и все доказательство моего 2-го утверждения. С помощью твоих примеров.

Можно много говорить: Microsoft, устарело и проч. и проч.

Но это все IMHO теоретические рассуждения, а жизнь их корректирует. Исходные тексты не инвариантны к средам разработки.

PS
Ну и совсем мелочь:

В конструкции
MyType MyVar = *Iterator последней инстанцией преобразования типов является опрератор=, а преобразования инкапсулированы ....
2.4K
19 декабря 2005 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Shida
[QUOTE]Originally posted by Alexandoros
А можно ли использовать итераторы с динамическими массивами? У меня есть 3-х мерный динамический массив и мне нужно работу с ним представить, как работу с итератором.



Если обычный массив, нечто вроде type MyArray[][][], то нельзя.

Итератор-это объект STL
Если для организации массива ты используешь vector, то можно.

3
19 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by dinasok51
Green

1. Я утверждал уже 2 раза и уверждаю в 3 раз:
В конструкции

MyType MyVar = *Iterator

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

Вопрос с Type& мы не рассматриваем, также как и массивы ссылок.


Ок. Согласен.

Цитата:
Originally posted by dinasok51
Green
2. И я утверждал, что возвращаемое значение в *iterator зависит от реализации STL, т.к. я с этим сталкивался.


Подожди... Ты хотел привязку к стандарту, я привязал.
Forward итератор, должен давать доступ к элементу контейнера, в общем случае это происходит возвращением ссылки на элемент. Об этом четко говорит стандарт.
С этим ты согласен?

К элементу vector<bool> достум может быть осуществлет только через прокси из-за вышеописанных особенностей этого контейнера. С этим ты согласен?
Если ты с этим не согласен, приведи, плз, пример доказывающий, что доступ к элементу vector<bool> возможен без прокси. Все равно, что будет доказательством, пример из конкретной реализации STL (при этом эта реализация должна отвечать пункту 23.2.5.2), либо собственоручно написанный итератор (опять же для контейнера соотв. пункту 23.2.5.2).

Цитата:
Originally posted by dinasok51

3.2 Якобы "доказательство номер 1"
// bool& b = *it;
Мы уже договаривались, не использовать аргументы, оскорбляющие умственные способности оппонента.


Никто никого не оскорблял. Для типа int (как и для других) я могу сделать такую запись

vector<int>::iterator it;
int& i = *it;

а для bool уже не могу. Что здесь оскорбительного?

Цитата:
Originally posted by dinasok51

VS 2003 компилирует все твои примеры.
VS6 SP6 образца 2004 года твое док-во номер 1 не компилирует.


VS6 вообще очень слабо соответствует стандарту, а в вопросе шаблонов, можно сказать, совсем не соответствует.
Вот ещё одно доказательство того, что разыменование итератора для vector<bool> возвращает прокси, а не bool:

Код:
#include <iostream>
#include <vector>


template<typename T>
void func(T)
{
    std::cout << "unspecified" << std::endl;
};

template<>
void func(bool)
{
    std::cout << "bool" << std::endl;
};

template<>
void func(std::vector<bool>::reference)
{
    std::cout << "std::vector<bool>::reference" << std::endl;
};

int main()
{
    std::vector<bool>::iterator it;
    func(*it);

    return 0;
}

Предупреждаю сразу, что на VS6 его можно даже не пытаться компилировать, т.к. VS6 не поддерживает частную специализацию.

Цитата:
Originally posted by dinasok51

Каждая конкретная РЕАЛИЗАЦИЯ STL работает несколько иначе, несмотря на наличие стандарта.
Во и все доказательство моего 2-го утверждения. С помощью твоих примеров.


Тогда зачем просить приводить цитаты из стандарта, для убедительности?

Цитата:
Originally posted by dinasok51

то все IMHO теоретические рассуждения, а жизнь их корректирует. Исходные тексты не инвариантны к средам разработки.


Пеняя на неидеальность реализации, можно объяснить вообще все.

Цитата:
Originally posted by dinasok51

В конструкции
MyType MyVar = *Iterator последней инстанцией преобразования типов является опрератор=, а преобразования инкапсулированы ....


Приведи, пожалуйста цитату из стандарта "для убедительности", что тип bool имеет оператор
operator=(const vector<bool>::reference&)

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

3
19 декабря 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by Shida
А можно ли использовать итераторы с динамическими массивами? У меня есть 3-х мерный динамический массив и мне нужно работу с ним представить, как работу с итератором.



Цитата:
Originally posted by Shida

Итератор-это объект STL
Если для организации массива ты используешь vector, то можно.



Я (уже) прошу прощения, но итератор - это в общем понимании паттерн проектирования или др. словами один из общепринятых способов (методов), а уж как частный случай - это реализация в STL на языке С++.

Поэтому, задание представить работу с динамическим массивом через итераторы можно расценить по-разному.
Никто не мешает создать свой итератор для обхода своего динамического массива, и для этого тебе не нужно превязываться к STL (хотя и можно).

Обобщенное описание итератора приведено здесь:
http://ooad.asf.ru/patterns/patterninfo.asp?id=19

В простейшем случае для массива итератором будет просто указатель на элемент массива.
Т.е. для твоего трехмерного массива, принимая во внимание, что в С++ все элементы будут расположены в памяти линейно, простейшим итератором будет просто указатель на элемент:

 
Код:
int MyArray[x][y][z];
int* it = &MyArray[0][0][0];  // инициализируем итератор адресом первого элемента

Естественно, такой итератор не отслеживает выход за пределы массива. Для этого можно написать соотв. класс итератора, с интерфейсом предоставляющим как минимум следующую функциональность:
1) шаг вперед (operator++), ;
2) (опционально) шаг назад (operator--), с проверкой на границу массива;
3) доступ к текущему элементу (operator*, operator->).

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог