Ich verwende eine interne Bibliothek , die zu imitieren eine entworfen wurden vorgeschlagen , C ++ Bibliothek , und irgendwann in den letzten Jahren sehe ich seine Oberfläche verändert verwenden std::string
zu string_view
.
Also ändere ich pflichtgemäß meinen Code, um mich an die neue Oberfläche anzupassen. Leider muss ich einen std :: string-Parameter und einen std :: string-Rückgabewert übergeben. Mein Code hat sich also wie folgt geändert:
void one_time_setup(const std::string & p1, int p2) {
api_class api;
api.setup (p1, special_number_to_string(p2));
}
zu
void one_time_setup(const std::string & p1, int p2) {
api_class api;
const std::string p2_storage(special_number_to_string(p2));
api.setup (string_view(&p1[0], p1.size()), string_view(&p2_storage[0], p2_storage.size()));
}
Ich verstehe wirklich nicht, was mir diese Änderung als API-Client gebracht hat, außer mehr Code (um es möglicherweise zu vermasseln). Der API-Aufruf ist weniger sicher (da die API den Speicher für ihre Parameter nicht mehr besitzt), hat wahrscheinlich die Arbeit meines Programms 0 gespeichert (aufgrund von Optimierungen, die Compiler jetzt ausführen können), und selbst wenn es Arbeit spart, wäre dies nur der Fall ein paar zuweisungen, die nach dem start oder in einer großen schleife irgendwo nicht mehr gemacht werden und nie mehr gemacht werden würden. Nicht für diese API.
Dieser Ansatz scheint jedoch den Ratschlägen zu folgen, die ich an anderer Stelle sehe, zum Beispiel die folgende Antwort :
Abgesehen davon sollten Sie seit C ++ 17 vermeiden, eine const std :: string & zugunsten einer std :: string_view zu übergeben:
Ich finde diesen Rat überraschend, da er das allgemeine Ersetzen eines relativ sicheren Objekts durch ein weniger sicheres (im Grunde genommen ein verherrlichter Zeiger und eine Länge) zu befürworten scheint, vor allem zu Optimierungszwecken.
Wann sollte string_view verwendet werden und wann nicht?
quelle
std::string_view
Konstruktor niemals direkt aufrufen müssen, sondern nur die Zeichenfolgen an die Methode übergeben, die einestd::string_view
direkte Konvertierung durchführt.<string>
Kopfzeile und geschieht automatisch. Dieser Code täuscht und ist falsch.Antworten:
std::string
(non-const, non-ref). Mit dieser Option können Sie einen Wert auch explizit verschieben, wenn Sie wissen, dass er im aufrufenden Kontext nie wieder verwendet wird.std::string_view
Fall ist, verwenden Sie (const, non-ref), dastring_view
dies problemlosstd::string
undchar*
ohne Ausgabe und ohne Anfertigung einer Kopie möglich ist. Dies sollte alleconst std::string&
Parameter ersetzen .Letztendlich sollten Sie niemals den
std::string_view
Konstruktor so aufrufen müssen, wie Sie es sind.std::string
hat einen Konvertierungsoperator , der die Konvertierung automatisch abwickelt.quelle
std::string_view
darum, die Verwendung zu vereinfachen. Wenn ein Entwickler es in einer Besitzersituation missbraucht, handelt es sich um einen Programmierfehler.std::string_view
ist streng nicht im Besitz.const, non-ref
? Der Parameter const hängt von der jeweiligen Verwendung ab, ist aber im Allgemeinen als nicht const sinnvoll. Und du hast 3const std::string_view &
an Stelle vonconst std::string &
?A
std::string_view
bringt einige der Vorteile von aconst char*
in C ++: Im Gegensatz zustd::string
einem string_viewstd::string&
.Dies bedeutet, dass eine string_view häufig Kopien vermeidet, ohne dass rohe Zeiger verwendet werden müssen.
In modernem Code
std::string_view
sollten fast alle Verwendungen vonconst std::string&
Funktionsparametern ersetzt werden. Dies sollte eine quellkompatible Änderung sein, da diesstd::string
einen Konvertierungsoperator zu deklariertstd::string_view
.Nur weil eine Zeichenfolgenansicht in Ihrem speziellen Anwendungsfall, in dem Sie ohnehin eine Zeichenfolge erstellen müssen, nicht hilft, bedeutet dies nicht, dass es im Allgemeinen eine schlechte Idee ist. Die C ++ - Standardbibliothek wurde eher aus Gründen der Allgemeinheit als der Benutzerfreundlichkeit optimiert. Das Argument „weniger sicher“ trifft nicht zu, da es nicht erforderlich sein sollte, die Zeichenfolgenansicht selbst zu erstellen.
quelle
std::string_view
ist das Fehlen einerc_str()
Methode, was zu unnötigen Zwischenobjekten führtstd::string
, die konstruiert und zugewiesen werden müssen. Dies ist insbesondere bei Low-Level-APIs ein Problem.abcdef\0
und eine Zeichenfolgenansicht haben, die auf diecde
Teilzeichenfolge zeigen, steht nach dem Zeichen "e
-" für die ursprüngliche Zeichenfolge keinf
Nullzeichen. Der Standard stellt außerdem fest: „data () kann einen Zeiger auf einen Puffer zurückgeben, der nicht mit Null terminiert ist. Daher ist es in der Regel ein Fehler, data () an eine Funktion zu übergeben, die nur ein const charT * enthält und eine nullterminierte Zeichenfolge erwartet. ”Ich denke, das ist ein leichtes Missverständnis des Zwecks. Während es sich um eine "Optimierung" handelt, sollten Sie es sich wirklich so vorstellen, als ob Sie sich von der Verwendung von a abkoppeln müssten
std::string
.Benutzer von C ++ haben Dutzende verschiedener Zeichenfolgenklassen erstellt. Zeichenfolgenklassen mit fester Länge, SSO-optimierte Klassen, wobei die Puffergröße ein Vorlagenparameter ist, Zeichenfolgenklassen, die einen Hashwert zum Vergleichen speichern, usw. Manche verwenden sogar COW-basierte Zeichenfolgen. Wenn es eine Sache gibt, die C ++ - Programmierer gerne tun, dann sind es Schreibzeichenfolgenklassen.
Dabei werden Zeichenfolgen ignoriert, die von C-Bibliotheken erstellt wurden und deren Eigentümer sie sind. Nackte
char*
s, vielleicht mit einer Größe von einer Art.Wenn Sie also eine Bibliothek schreiben und eine nehmen
const std::string&
, muss der Benutzer jetzt die Zeichenfolge, die er verwendet hat, nehmen und in eine kopierenstd::string
. Vielleicht Dutzende Male.Wenn Sie auf die zeichenfolgenspezifische
std::string
Schnittstelle zugreifen möchten , warum sollten Sie die Zeichenfolge kopieren müssen ? Das ist so eine Verschwendung.Die Hauptgründe, a nicht
string_view
als Parameter zu verwenden, sind:Wenn Ihr Endziel darin besteht, die Zeichenfolge an eine Schnittstelle zu übergeben, die eine mit NUL abgeschlossene Zeichenfolge (
fopen
usw.) verwendet.std::string
wird garantiert, um NUL beendet zu werden;string_view
ist nicht. Und es ist sehr einfach, eine Ansicht mit Teilzeichenfolgen zu versehen, damit sie nicht mit NUL abgeschlossen wird. Unterzeichenfolge astd::string
kopiert die Teilzeichenfolge in einen mit NUL abgeschlossenen Bereich.Für genau dieses Szenario habe ich einen speziellen NUL-terminierten string_view-Stiltyp geschrieben. Sie können die meisten Vorgänge ausführen, jedoch keine Vorgänge, die den NUL-terminierten Status aufheben (z. B. Trimmen vom Ende).
Probleme auf Lebenszeit. Wenn Sie das wirklich kopieren müssen
std::string
oder das Array von Zeichen den Funktionsaufruf überlebt haben, geben Sie dies am besten im Voraus mit a anconst std::string &
. Oder einfachstd::string
als Wertparameter. Auf diese Weise können Sie, wenn sie bereits über eine solche Zeichenfolge verfügen, sofort den Besitz der Zeichenfolge beanspruchen, und der Anrufer kann in die Zeichenfolge wechseln, wenn er keine Kopie der Zeichenfolge aufbewahren muss.quelle
string_view
ist eine Verkehrssprache, die mit allem umgehen kann.string_view
ist es einfach.