c++ - Soll ich einen std::string mit "string" oder "string" vergleichen?




c++14 c++17 (2)

Betrachten Sie dieses Code-Snippet:

bool foo(const std::string& s) {
    return s == "hello"; // comparing against a const char* literal
}

bool bar(const std::string& s) {
    return s == "hello"s; // comparing against a std::string literal
}

Auf den ersten Blick sieht es so aus, als würde ein Vergleich mit einem const char* weniger Assembler-Anweisungen 1 erfordern, da die Verwendung eines String-Literal zu einer In-Place-Konstruktion des std::string .

Betrachten Sie jedoch den operator==(const char*, const std::string&) :

Alle Vergleiche werden über die Mitgliedsfunktion compare() .

Nach meinem Verständnis bedeutet dies, dass wir ohnehin einen std::string erstellen müssen, um den Vergleich durchzuführen. Ich vermute, dass der Overhead am Ende derselbe sein wird (obwohl er durch den Aufruf von operator== verborgen wird).

( EDIT: Wie bereits in den Antworten erwähnt, habe ich vergessen, dass effektiv an s.compare(const char*) in foo() aufgerufen wird, daher findet in diesem Fall natürlich keine In-Place-Konstruktion statt. )

  • Welchen Vergleich soll ich bevorzugen?
  • Hat eine Version Vorteile gegenüber der anderen (möglicherweise in bestimmten Situationen)?

1 Ich bin mir bewusst, dass weniger Montageanweisungen nicht unbedingt schnelleren Code bedeuten, aber ich möchte hier nicht auf das Micro-Benchmarking eingehen.


Nach meinem Verständnis bedeutet dies, dass wir ohnehin einen std::string erstellen müssen, um den Vergleich durchzuführen. Ich vermute, dass der Overhead am Ende derselbe sein wird (obwohl er durch den Aufruf von operator== verborgen wird).

Hier geht diese Argumentation fehl. std::compare muss seinen Operanden nicht als nullterminierte Zeichenfolge im C-Stil zuweisen, um zu funktionieren. Nach einer der Überladungen:

int compare( const CharT* s ) const; // (4)

4) Vergleicht diese Zeichenfolge mit der nullterminierten Zeichenfolge, die mit dem Zeichen beginnt, auf das durch s mit length Traits::length(s) verwiesen wird.

Die Zuweisung oder Nichtzuweisung ist zwar ein Implementierungsdetail, ein Sequenzvergleich erscheint jedoch nicht sinnvoll.


Weder.

Wenn Sie clever sein wollen, vergleichen Sie mit "string"sv , was eine std::string_view .

Der Vergleich mit einem Literal wie "string" führt zwar nicht zu einem Zuordnungsaufwand, wird jedoch als nullterminierter String mit allen damit verbundenen Nachteilen behandelt: Keine Toleranz für eingebettete Nullen, und Benutzer müssen das Nullterminator beachten.

"string"s führt eine Zuweisung durch, abgesehen von small-string-optimisation oder der Zuweisungsentscheidung . Außerdem wird dem Operator die Länge des Literal übergeben, ohne dass gezählt werden muss, und es werden eingebettete Nullen zugelassen.

Und schließlich kombiniert die Verwendung von "string"sv die Vorteile der beiden anderen Ansätze und vermeidet deren individuelle Nachteile. Außerdem ist eine std::string_view eine weitaus einfachere Bestie als eine std::string , insbesondere wenn diese SSO verwendet, wie alle modernen.

Spätestens seit C ++ 14 (das allgemein erlaubte, Zuweisungen aufzuheben) konnten Compiler theoretisch alle Optionen auf die letzte optimieren, vorausgesetzt, dass genügend Informationen (allgemein verfügbar für das Beispiel) und Aufwand vorhanden waren, unter der Regel, als ob . Wir sind aber noch nicht da.





string-literals