Ich finde das Verhalten von std::string::find
inkonsistent mit Standard-C ++ - Containern.
Z.B
std::map<int, int> myMap = {{1, 2}};
auto it = myMap.find(10); // it == myMap.end()
Aber für eine Schnur,
std::string myStr = "hello";
auto it = myStr.find('!'); // it == std::string::npos
Warum sollte die fehlgeschlagene myStr.find('!')
Rückkehr nicht myStr.end()
statt std::string::npos
?
Da das std::string
im Vergleich zu anderen Containern etwas Besonderes ist, frage ich mich, ob es einen wirklichen Grund dafür gibt. (Überraschenderweise konnte ich nirgendwo jemanden finden, der dies in Frage stellte).
c++
stdstring
c++-standard-library
Sumudu
quelle
quelle
std::string
intern aus Zeichen besteht, die kostengünstige Elemente sind (in Bezug auf das Gedächtnis). Außerdem ist Zeichen der einzige Typ, derstd::string
enthalten kann.std::map
Besteht dagegen aus komplexeren Elementen. Außerdemstd::map::find
sagt die Spezifikation von , dass es ein Element finden soll, und die Spezifikation vonstd::string::find
sagt, dass es seine Aufgabe ist, Position zu finden.Antworten:
Zunächst
std::string
ist bekannt, dass die Benutzeroberfläche aufgebläht und inkonsistent ist, siehe Herb Sutters Gotw84 zu diesem Thema. Es gibt jedoch eine Begründung für diestd::string::find
Rückgabe eines Index :std::string::substr
. Diese Convenience-Member-Funktion arbeitet mit Indizes, zSie könnten so implementieren
substr
, dass Iteratoren in die Zeichenfolge aufgenommen werden, aber dann müssten wir nicht lange auf laute Beschwerden warten,std::string
die unbrauchbar und nicht intuitiv sind. Wenn Sie alsostd::string::substr
Indizes akzeptieren, wie würden Sie den Index des ersten Auftretens'd'
in der obigen Eingabezeichenfolge finden, um alles ausgehend von dieser Teilzeichenfolge auszudrucken?Dies ist möglicherweise auch nicht das, was Sie wollen. Daher können wir
std::string::find
einen Index zurückgeben lassen, und hier sind wir:Wenn Sie mit Iteratoren arbeiten möchten, verwenden Sie
<algorithm>
. Sie erlauben Ihnen die oben genannten alsquelle
std::string::find
könnte jedoch immer noch zurückgegeben werdensize()
, anstattnpos
die Kompatibilität mitsubstr
beizubehalten und gleichzeitig einige zusätzliche Vorteile zu vermeiden.std::string::substr
deckt aber bereits den Fall "Start hier bis zum Ende" mit einem Standardparameter für den zweiten Index (npos
) ab. Ich denke, eine Rückkehrsize()
wäre auch verwirrend und ein buchstäblicher Wächter wienpos
könnte die bessere Wahl sein?!std::string::find
ein Iterator zurückgegeben wird,std::string::substr
würde wahrscheinlich auch ein Iterator für die Startposition akzeptiert. Ihr Beispiel mit find würde in dieser alternativen Welt in beiden Fällen gleich aussehen.std::string::substr
mit einem Iterator Argumente öffnet die Tür für einen weiteren UB Fall (neben dem past-the-End - Szenario , das genauso gut mit Indizes oder Iteratoren passieren kann): Leiten einen Iterator, der auf einem andere Zeichenfolge bezieht.Dies liegt daran,
std::string
dass zwei Schnittstellen vorhanden sind:std::string
spezifische indexbasierte Schnittstellestd::string::find
ist Teil der indexbasierten Schnittstelle und gibt daher Indizes zurück.Verwenden Sie
std::find
diese Option , um die allgemeine iteratorbasierte Schnittstelle zu verwenden.Verwenden
std::vector<char>
Sie diese Option, wenn Sie die indexbasierte Schnittstelle nicht möchten (tun Sie dies nicht).quelle