2009-05-10 3 views
9

Мне было интересно, как устанавливается равенство (==) для итераторов STL? Является ли это простым сопоставлением указателей (и, следовательно, основанным на адресах) или чем-то более причудливым?Как устанавливается равенство итератора STL?

Если у меня есть два итератора из двух разных объектов списка, и я их сравниваю, будет ли результат всегда быть ложным?

А что, если я сравню действительное значение с тем, что выходит за пределы допустимого диапазона? Это всегда ложь?

ответ

11

Классы итераторов могут определять перегруженные == операторы, если они этого захотят. Таким образом, результат зависит от реализации operator==.

Вы не должны сравнивать итераторы разных контейнеров. Я думаю, что некоторые отладочные реализации STL будут сигнализировать о предупреждении, если вы это сделаете, что поможет вам уловить случаи этого ошибочного использования в вашем коде.

+6

На самом деле не должно быть? Вы, конечно же, не должны! – xtofl

+0

Возможность технически сравнивать итераторы из разных контейнеров делает MSVC источником раздражающего предупреждения об устаревании при использовании 'std :: copy' ... –

2

Мне было интересно, как устанавливается равенство (==) для итераторов STL?

Не все итераторы могут сравниваться (например, выходные Итераторы не обязаны предоставлять op==). Вы можете использовать operator==, когда концепция диапазона четко определена для рассматриваемой категории итератора.

Является ли это простым сопоставлением указателей (и, следовательно, основанным на адресах) или чем-то более причудливым?

Итераторы всегда применяются с указателями. Изменить: Я говорю , реализованный с - который относится не к стандартным требованиям, а скорее к практике использования poitners в качестве базовой конструкции. У реализации (например, VS) могут быть введены специальные проверки проверки.

Если у меня есть два итератора из двух разных объектов списка, и я их сравниваю, будет ли результат всегда быть ложным?

Вы вызываете Неопределенное поведение.

А что, если я сравню действительное значение с тем, что выходит за пределы допустимого диапазона? Это всегда ложь?

Опять же, вы будете использовать UB. Единственное допустимое сравнение - это два итератора в одном и том же диапазоне или один в диапазоне, а другой - один за последним элементом. Обратите внимание: вы можете сравнивать только с итератором с одним прошлым за последним элементом, разыгрывая то же самое, что приводит к UB.

+4

« Итераторы всегда реализуются как указатели ». Я не думаю, что insert_iterator - простой указатель.Я ожидал бы, что это объект, содержащий указатель или ссылку на контейнер, плюс итератор на этом контейнере. –

+0

Посмотрите. Реализации, которые я видел, используют указатель на контейнер. – dirkgently

+2

Только std :: vector :: iterator гарантированно может быть конвертирован в указатель. Многие, вероятно, _use_ указатели на свои узлы. Некоторые используют два указателя. Некоторые могут использовать указатель файла. Можете ли вы утверждать, что они реализованы в качестве указателей? Я так не думаю. Я бы не осмелился основывать на этом какой-либо дизайн. – xtofl

1

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

Итераторы не всегда являются указателями, и действительно, в некоторых «безопасных» версиях STL никогда не указатели. Итераторы для векторов и строк обычно реализуются как указатели, потому что они могут быть. Итераторы для классов, списков, наборов и карт не могут быть указателями в любой половине эффективной реализации.

Какие итераторы являются типом умного указателя. Они следуют общему принципу: если они выглядят и ведут себя как указатель, то они являются указателем, насколько это касается пользователя.

3

Дэниел спросил: мне было интересно, как равенство (==) создан для STL итераторы? Является ли это простым сопоставлением указателей (и, следовательно, основанным на адресах) или чем-то более фантастическим?

Это зависит от реализации. Прямо сейчас, на Visual C++ 2008, я вижу следующий код (для списка итератора):

bool operator==(const _Myt_iter& _Right) const 
{ // test for iterator equality 

#if _HAS_ITERATOR_DEBUGGING 
    _Compat(_Right); 
#else 
    _SCL_SECURE_TRAITS_VALIDATE(this->_Has_container() && this->_Same_container(_Right)); 
#endif /* _HAS_ITERATOR_DEBUGGING */ 

    return (_Ptr == _Right._Ptr); 
} 

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

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

Даниил спросил: Если у меня есть два итератора из двух разных объектов списка, и я их сравнивать, будет результат всегда будет ложным?

До сих пор, по-видимому, стандарт был несколько неясным по этому вопросу. По-видимому, они будут явно писать, что этот вид деятельности имеет неопределенные результаты:

Цитирование: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#446

В результате использования любой операции итератора (24.2.1 [input.iterators], 24.2.2 [output.iterators], 24.2.3 [forward.iterators], 24.2.4 [bidirectional.iterators], 24.2.5 [random.access.iterators]) , который использует два значения итератора в качестве аргументов (сноска) которые были полученные из двух разных диапазонов r1 и r2 (включая их значения конца прошлого), которые не являются поддиапазонами одного общего диапазона не определено, если явно не указано иначе.

сноска) Среди других эти операции ==, <, бинарная - и скопировать назначение

Так что я предполагаю, что это зло сравнить итератор из разных контейнеров ... ^ _^

Daniel спросил: А что, если я сравню действительное значение с тем, что выходит за пределы допустимого диапазона? Это всегда ложь?

То же, что и выше.

Смежные вопросы