Почему string::find возвращает size_type, а не итератор?

Почему в С++ string::find возвращает size_type, а не iterator?

Это имело бы смысл, потому что такие функции, как string::replace или string::insert, принимают итераторы в качестве входных данных, поэтому вы можете find какой-то символ и сразу же передать возвращенный итератор replace и т. д.

Кроме того, std::find возвращает итератор — чем отличается std::string::find?


person Frank    schedule 17.06.2010    source источник
comment
В основном исторические причины. Кроме того, из-за этого плохого дизайна я провалил последнее техническое собеседование, когда смешивал iterator и size_t.   -  person JP Zhang    schedule 22.10.2020


Ответы (4)


Дизайн блестящего нового строкового класса стандартной библиотеки уже был готов, когда Страуструп представил STL комитету по стандартизации. Комитету понравился STL, и он начал включать его в стандарт, тем самым адаптировав большую часть того, о чем они уже договорились (и, вероятно, также отложив стандарт еще на год или два).

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

Не всегда легко догадаться, почему некоторые функции-члены имеют только версии, принимающие индексы, а некоторые — версии, использующие итераторы. Однако в случае std::basic_string<>::find() все кажется простым: поскольку std::find() уже возвращает итератор, std::basic_string<>::find() оставили как есть.

person sbi    schedule 17.06.2010
comment
Ваш последний абзац сбивает с толку. Вы имеете в виду, имеет ли смысл, чтобы basic_string‹›::find() возвращал size_type, потому что std::find() уже возвращает итератор, и разработчики не хотят дублировать это поведение? Разве не имеет смысла сделать их похожими, улучшив соответствие и удобство использования библиотеки? - person Frank; 17.06.2010
comment
@dehmann в основном, если вам нужен итератор, используйте std::find(), если вам нужен индекс, используйте std::basic_string‹›::find() - person Mr Shunz; 17.06.2010
comment
@dehmann: Посмотрите на это с исторической точки зрения: они добавили функции-члены, работающие с итераторами только там, где алгоритмы STL не годились. Поскольку std::find() отлично работает со строками, не было необходимости в другой функции поиска, возвращающей итератор как член класса строки. Так что std::basic_string<>::find() оставили как есть. - person sbi; 17.06.2010
comment
@sbi Предполагая, что кто-то ищет подстроку, а не один символ, я думаю, что std::search(), а не std::find() будет способом получить результат итератора. Но это может быть не так эффективно, как std::basic_string<>::find() (в зависимости от искателя после C++17). - person Andrew Moylan; 22.05.2017
comment
Помоги мне здесь, @Andrew. Почему функция, предназначенная для поиска последовательности элементов в другой последовательности элементов, может быть менее эффективной, чем функция, предназначенная для поиска последовательности символов в другой последовательности символов? - person sbi; 01.06.2017
comment
Я имел в виду эмпирическое наблюдение, согласно которому std::basic_string<>::find(), по-видимому, равно O(n*m), тогда как с помощью std::search() можно было бы выбрать тип поисковика O(n+m), если это необходимо. - person Andrew Moylan; 02.06.2017
comment
@AndrewMoylan: Мой ответ и мои комментарии относятся к дизайну класса строк в середине-конце 90-х. Поисковики появились в C++17. - person sbi; 19.06.2017

Вероятно, более полезно получить число из find, потому что тогда вы можете использовать оператор [] или substr(), чтобы получить символы, которые вы только что искали.

Кроме того, если вам нужен итератор, вы всегда можете сделать begin() + pos

person shoosh    schedule 17.06.2010
comment
Так вы говорите, что плохой интерфейс string::find на самом деле хорош, потому что он хорошо взаимодействует с плохим интерфейсом string::substr? ;) - person Praxeolitic; 12.10.2015
comment
Я бы не хотел возиться с итераторами, когда все, что я хочу, это получить первые две буквы строки. - person shoosh; 12.10.2015
comment
нравится: begin() + pos - person fchen; 10.05.2016
comment
Давайте поговорим о счастье, когда вы используете string::substr(), а string::find() рад вернуть string::npos. - person alextoind; 31.01.2017

Все строковые функции работают с индексами, некоторые функции (такие как replace() и insert()) просто дополнительно поддерживают итераторы. Таким образом, результат find() может напрямую использоваться в этих функциях. Поскольку не может быть двух функций find(), которые отличаются только типом возвращаемого значения (одна возвращает итератор, другая возвращает индекс), необходимо было выбрать одну.

person sth    schedule 17.06.2010

Я предполагаю, что это связано с тем, что обычно строковые члены работают с индексами, а не с итераторами, и это упрощает использование возвращаемого значения. Вы всегда можете использовать std::find, если хотите получить итератор.

person Mark B    schedule 17.06.2010
comment
Я просто хотел сказать, что std::vector также по своей сути работает с индексами и не возвращает size_type, когда вы что-то ищете, но потом я вспомнил, что у вектора вообще нет find(). Заставляет задуматься, почему он у string... - person Frank; 17.06.2010
comment
@dehmann: по историческим причинам. Сначала был std::string (затем std::basic_string), а затем появился STL с его итераторами. Когда было решено включить STL в стандарт, фактически считалось, что он близок к окончательной доработке. (Включение STL задержало его примерно на год.) На самом деле уже использовались реализации std::basic_string. Так что изменения были минимальными и в основном только дополнениями. - person sbi; 17.06.2010