2017-01-11 13 views
0

Я знаю, что std::list итераторы are Equality Comparable (как двунаправленные итераторы). Теперь, следующий код четко определен и гарантированно печатает «равный»?Являются ли std :: list итераторами уникальными и постоянными?

std::list<int> nums = { 1, 2, 3 }; 
std::list<int>::iterator a = std::find(nums.begin(), nums.end(), 1); 
nums.push_front(0); 
std::list<int>::iterator b = std::find(nums.begin(), nums.end(), 1); 
if (a == b) std::cout << "equal" << std::endl; 

works for me Это, но это не значит, что это хорошо определено или гарантировано!

Другими словами, если вы найдете итератор для конкретной записи std::list в разное время (возможно, с добавлением или удалением других элементов между ними), являются ли два итератора гарантированными равными?

Этот вопрос, в частности, касается итераторов std::list (если это имеет значение), но ответ, который также охватывает другие контейнеры STL в целом, был бы отличным!

ответ

2

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

[forward.iterators] (проект стандарта)

5 Если а и Ь равно, то либо а и б оба разыменовываемые, либо ни один не разыменовываемый.

6 Если a и b являются разыменованными, тогда a == b тогда и только тогда, когда * a и * b связаны с одним и тем же объектом.

Поскольку ваши итераторы a и b указывают на один и тот же объект, они должны сравнивать равные.


(возможно, с другими элементами будучи добавлены или удалены между ними)

Для некоторых контейнеров, это может оказать влияние на действительность итератора, который был создан до модификации. Если один из итераторов недействителен, то больше не гарантируется указание на объект, к которому он привык. Фактически, больше не будет гарантировано указывать на контейнер вообще, поэтому результат сравнения не будет определен.

В частности, нетературные итераторы std::list не будут признаны недействительными, если не будет удален конкретный элемент, на который они указывают. Каждый контейнер имеет свои собственные правила недействительности, которые необходимо искать из документации.

2

Да. Это гарантируется для std::list, но не для (скажем) вектора.

[list.modifiers]/1 говорит (о всех вызовов для вставки, push_back и т.д.): "Замечания: не влияет на действительность итераторов и ссылок"

[vector.modifiers]/1 вместо: «Примечания: вызывает перераспределение, если новый размер больше старой емкости. Перераспределение делает недействительными все ссылки, указатели и итераторы, ссылающиеся на элементы в последовательности. Если перераспределение не происходит, все итераторы и ссылки до того, как точка ввода останется в силе. "