Я считаю, что поведение std::string::find
несовместимо со стандартными контейнерами C ++.
Например
std::map<int, int> myMap = {{1, 2}};
auto it = myMap.find(10); // it == myMap.end()
Но для строки,
std::string myStr = "hello";
auto it = myStr.find('!'); // it == std::string::npos
Почему бы не myStr.find('!')
вернуть неудачу myStr.end()
вместо std::string::npos
?
Поскольку std::string
он несколько особенный по сравнению с другими контейнерами, мне интересно, есть ли какая-то реальная причина этого. (Удивительно, но я не смог найти никого, кто бы это допрашивал).
c++
stdstring
c++-standard-library
Sumudu
источник
источник
std::string
внутренне состоит из символов, которые являются недорогими элементами (в отношении памяти). И, кроме того, символ - единственный тип, которыйstd::string
может содержать. С другой стороны,std::map
состоит из более сложных элементов. Кроме того, спецификацияstd::map::find
говорит, что он должен найти элемент, а спецификацияstd::string::find
говорит, что его задача - найти позицию.Ответы:
Начнем с того, что
std::string
интерфейс, как известно, раздутый и противоречивый, см. Gotw84 Херба Саттера на эту тему. Но , тем не менее, есть обоснованиеstd::string::find
возвращения индекса:std::string::substr
. Эта удобная функция-член работает с индексами, напримерВы могли бы реализовать так
substr
, чтобы он принимал итераторы в строку, но тогда нам не пришлось бы долго ждать громких жалоб, которыеstd::string
непригодны и противоречивы. Итак, учитывая, что онstd::string::substr
принимает индексы, как бы вы нашли индекс первого вхождения'd'
в указанной выше входной строке, чтобы распечатать все, начиная с этой подстроки?Это также может быть не то, что вы хотите. Следовательно, мы можем позволить
std::string::find
вернуть индекс, и вот мы здесь:Если вы хотите работать с итераторами, используйте
<algorithm>
. Они позволяют вам как вышеисточник
std::string::find
он все равно мог бы вернутьsize()
вместоnpos
сохранения совместимостиsubstr
, а также избежать нескольких дополнительных браков.std::string::substr
уже охватывает случай «от начала до конца» с параметром по умолчанию для второго индекса (npos
). Я думаю, что возвращениеsize()
также может сбить с толку, и иметь буквального дозорного, какnpos
может быть лучшим выбором ?!std::string::find
возвращает итератор,std::string::substr
вероятно, также принял бы итератор для начальной позиции. Ваш пример с find будет выглядеть одинаково в обоих случаях в этом альтернативном мире.std::string::substr
с аргументом итератора открывается дверь для еще одного случая UB (помимо сценария «за конец», который может одинаково хорошо происходить с индексами или итераторами): передача итератора, который ссылается на другую строку.Это потому
std::string
, что есть два интерфейса:std::string
Конкретный индекс на основе интерфейсаstd::string::find
является частью интерфейса, основанного на индексах , и поэтому возвращает индексы.Используйте
std::find
для использования общего интерфейса на основе итератора.Используйте,
std::vector<char>
если вам не нужен интерфейс на основе индекса (не делайте этого).источник