Klassen für String-Daten
Überblick
Diese Seite gibt einen Überblick über die String-Klassen in Qt, insbesondere über die große Anzahl von String-Containern und deren effiziente Verwendung in performance-kritischem Code.
Die folgenden Anleitungen zur effizienten Nutzung richten sich an erfahrene Entwickler, die an leistungsrelevantem Code arbeiten, der erhebliche Mengen an String-Verarbeitung enthält. Dies ist z.B. ein Parser oder ein Textdateigenerator. Im Allgemeinen kann QString überall eingesetzt werden und es wird gut funktionieren. Es bietet auch APIs für den Umgang mit verschiedenen Kodierungen (zum Beispiel QString::fromLatin1()). Für viele Anwendungen und vor allem, wenn die String-Verarbeitung für die Leistung eine unbedeutende Rolle spielt, wird QString eine einfache und ausreichende Lösung sein. Einige Qt-Funktionen geben ein QStringView zurück, das bei Bedarf mit QStringView::toString() in ein QString umgewandelt werden kann.
Wirkungsvolle Tipps
Die folgenden drei Regeln verbessern den Umgang mit Strings erheblich, ohne die Komplexität zu sehr zu erhöhen. Befolgen Sie diese Regeln, um in den meisten Fällen eine nahezu optimale Leistung zu erzielen. Die ersten beiden Regeln betreffen die Kodierung von String-Literalen und deren Markierung im Quellcode. Die dritte Regel befasst sich mit tiefen Kopien bei der Verwendung von Teilen einer Zeichenkette.
- Alle Strings, die nur ASCII-Zeichen enthalten (z. B. Logmeldungen), können mit Latin-1 kodiert werden. Verwenden Sie die string literal
"foo"_L1
. Ohne dieses Suffix wird davon ausgegangen, dass Zeichenkettenliterale im Quellcode UTF-8-kodiert sind, und ihre Verarbeitung wird langsamer. Versuchen Sie im Allgemeinen, die engste Kodierung zu verwenden, was in vielen Fällen Latin-1 ist. - Für den Benutzer sichtbare Zeichenketten werden in der Regel übersetzt und daher durch die Funktion QObject::tr() geleitet. Diese Funktion nimmt ein String-Literal (const char array) und gibt ein QString mit UTF-16-Kodierung zurück, wie es von allen UI-Elementen verlangt wird. Wenn die Übersetzungsinfrastruktur nicht verwendet wird, sollten Sie in der gesamten Anwendung UTF-16-Kodierung verwenden. Verwenden Sie das String-Literal
u"foo"
, um UTF-16-Stringliterale zu erzeugen, oder das Qt-spezifische Literalu"foo"_s
, um direkt ein QString zu erzeugen. - Wenn Sie Teile eines QString verarbeiten, erstellen Sie stattdessen QStringView Objekte, anstatt jeden Teil in sein eigenes QString Objekt zu kopieren. Diese können mit QStringView::toString() zurück nach QString konvertiert werden, aber vermeiden Sie dies so weit wie möglich. Wenn Funktionen QStringView zurückgeben, ist es am effizientesten, weiterhin mit dieser Klasse zu arbeiten, wenn möglich. Die API ist vergleichbar mit einer Konstante QString.
Effiziente Nutzung
Um String-Klassen effizient zu nutzen, sollte man die drei folgenden Konzepte verstehen:
- Kodierung
- Eigene und nicht-eigene Container
- Literale
Kodierung
Qt unterstützt UTF-16, UTF-8, Latin-1 (ISO 8859-1) und US-ASCII (das ist die gemeinsame Untermenge von Latin-1 und UTF-8) in der einen oder anderen Form.
- Latin-1 ist eine Zeichenkodierung, die ein einziges Byte pro Zeichen verwendet, was sie zur effizientesten, aber auch begrenztesten Kodierung macht.
- UTF-8 ist eine Zeichenkodierung mit variabler Länge, die alle Zeichen mit einem bis vier Bytes kodiert. Sie ist abwärtskompatibel zu US-ASCII und ist die gängige Kodierung für Quellcode und ähnliche Dateien. Qt geht davon aus, dass der Quellcode in UTF-8 kodiert ist.
- UTF-16 ist eine Kodierung mit variabler Länge, die zwei oder vier Bytes pro Zeichen verwendet. Es ist die übliche Kodierung für benutzerexponierten Text in Qt.
Siehe die Informationen über die Unterstützung von Unicode in Qt für weitere Informationen.
Andere Kodierungen werden in Form von einzelnen Funktionen wie QString::fromUcs4() oder der QStringConverter Klassen unterstützt. Darüber hinaus bietet Qt einen kodierungsunabhängigen Container für Daten, QByteArray, der sich gut für die Speicherung von Binärdaten eignet. QAnyStringView behält die Kodierung der zugrundeliegenden Zeichenkette im Auge und kann somit eine Sicht auf Zeichenketten mit jedem der unterstützten Kodierungsstandards bieten.
Die Konvertierung zwischen den Kodierungen ist kostspielig, daher sollte sie nach Möglichkeit vermieden werden. Andererseits kann eine kompaktere Kodierung, insbesondere für Stringliterale, die binäre Größe verringern, was die Leistung steigern kann. Wenn String-Literale in Latin-1 ausgedrückt werden können, stellt dies einen guten Kompromiss zwischen diesen konkurrierenden Faktoren dar, selbst wenn sie irgendwann in UTF-16 konvertiert werden müssen. Wenn eine Latin-1-Zeichenkette in ein QString konvertiert werden muss, geschieht dies relativ effizient.
Funktionsweise
String-Klassen lassen sich weiter nach der Funktionalität unterscheiden, die sie unterstützen. Eine wichtige Unterscheidung ist, ob sie ihre Daten besitzen und somit kontrollieren oder ob sie lediglich auf Daten verweisen, die an anderer Stelle gehalten werden. Erstere werden als eigene Container bezeichnet, letztere als nicht-eigene Container oder Views. Ein nicht-eigener Containertyp zeichnet in der Regel nur einen Zeiger auf den Anfang der Daten und ihre Größe auf, was ihn leicht und billig macht, aber er bleibt nur so lange gültig, wie die Daten verfügbar sind. Ein eigener String verwaltet den Speicher, in dem er seine Daten speichert, und stellt sicher, dass die Daten während der gesamten Lebensdauer des Containers verfügbar bleiben, aber seine Erstellung und Zerstörung verursacht Kosten für die Zuweisung und Freigabe von Speicher. Sichten unterstützen in der Regel eine Teilmenge der Funktionen der eigenen Zeichenfolge, ohne die Möglichkeit, die zugrunde liegenden Daten zu ändern.
Daher eignen sich String-Views besonders gut für die Darstellung von Teilen größerer Strings, z. B. in einem Parser, während Owning Strings gut für die persistente Speicherung geeignet sind, z. B. für Mitglieder einer Klasse. Wenn eine Funktion eine Zeichenkette zurückgibt, die sie selbst konstruiert hat, z.B. durch das Kombinieren von Fragmenten, muss sie eine besitzende Zeichenkette zurückgeben; aber wenn eine Funktion einen Teil einer persistent gespeicherten Zeichenkette zurückgibt, ist eine Ansicht normalerweise besser geeignet.
Beachten Sie, dass besitzende Container in Qt ihre Daten implizit teilen, was bedeutet, dass es auch effizient ist, große Container als Wert zu übergeben oder zurückzugeben, obwohl dies aufgrund der Referenzzählung etwas weniger effizient ist als die Übergabe per Referenz. Wenn Sie den impliziten Data-Sharing-Mechanismus von Qt-Klassen nutzen wollen, müssen Sie den String als eigenen Container oder eine Referenz auf einen solchen übergeben. Die Konvertierung in einen View und zurück wird immer eine zusätzliche Kopie der Daten erzeugen.
Schließlich bietet Qt Klassen für einzelne Zeichen, Listen von Strings und String Matcher. Diese Klassen sind für die meisten unterstützten Kodierungsstandards in Qt verfügbar, mit einigen Ausnahmen. Funktionalität auf höherer Ebene wird von spezialisierten Klassen wie QLocale oder QTextBoundaryFinder bereitgestellt. Diese High-Level-Klassen basieren in der Regel auf QString und seiner UTF-16-Kodierung. Einige Klassen sind Vorlagen und arbeiten mit allen verfügbaren String-Klassen.
Literale
Der C++-Standard bietet String-Literale, um Strings zur Kompilierzeit zu erstellen. Es gibt von der Sprache definierte Stringliterale und von Qt definierte Literale, sogenannte benutzerdefinierte Literale. Ein von C++ definiertes Stringliteral ist in doppelte Anführungszeichen eingeschlossen und kann ein Präfix haben, das dem Compiler mitteilt, wie der Inhalt zu interpretieren ist. Für Qt ist das UTF-16-Stringliteral u"foo"
das wichtigste. Es erzeugt einen String, der zur Kompilierzeit in UTF-16 kodiert ist und erspart die Konvertierung aus einer anderen Kodierung zur Laufzeit. QStringView kann einfach und effizient aus einem String-Literal konstruiert werden, so dass es an Funktionen übergeben werden kann, die ein QStringView Argument akzeptieren (oder, als Ergebnis, ein QAnyStringView).
Benutzerdefinierte Literale haben die gleiche Form wie die von C++ definierten, fügen aber ein Suffix nach dem schließenden Anführungszeichen hinzu. Die Kodierung wird weiterhin durch das Präfix bestimmt, aber das resultierende Literal wird verwendet, um ein Objekt eines benutzerdefinierten Typs zu konstruieren. Qt definiert diese daher für einige seiner eigenen String-Typen: u"foo"_s
für QString, "foo"_L1
für QLatin1StringView und u"foo"_ba
für QByteArray. Diese werden durch die Verwendung von StringLiterals Namespace bereitgestellt. Ein einfaches C++-Stringliteral "foo"
wird als UTF-8 verstanden und die Konvertierung in QString und damit in UTF-16 wird teuer sein. Wenn Sie String-Literale in einfachem ASCII haben, verwenden Sie "foo"_L1
, um sie als Latin-1 zu interpretieren, und profitieren Sie von den oben beschriebenen Vorteilen.
Grundlegende String-Klassen
Die folgende Tabelle gibt einen Überblick über die grundlegenden String-Klassen für die verschiedenen Standards der Textkodierung.
Kodierung | C++ String-Literal | Qt benutzerdefiniertes Literal | C++ Zeichen | Qt Zeichen | Eigene Zeichenkette | Nicht-eigene Zeichenkette |
---|---|---|---|---|---|---|
Lateinisch-1 | - | ""_L1 | - | QLatin1Char | - | QLatin1StringView |
UTF-8 | u8"" | - | char8_t | - | - | QUtf8StringView |
UTF-16 | u"" | u""_s | char16_t | QChar | QString | QStringView |
Binär/Keine | - | ""_ba | std::byte | - | QByteArray | QByteArrayView |
Flexibel | beliebig | - | - | - | - | QAnyStringView |
Einige der fehlenden Einträge können durch integrierte C++-Typen und Typen der Standardbibliothek ersetzt werden: Eine eigene Latin-1- oder UTF-8-kodierte Zeichenkette kann std::string
oder ein beliebiges 8-Bit-Array char
sein. QStringView kann auch auf beliebige 16-Bit-Zeichenarrays verweisen, wie std::u16string oder std::wstring auf einigen Plattformen.
Qt bietet auch spezialisierte Listen für einige dieser Typen, nämlich QStringList und QByteArrayView, sowie Matcher, QLatin1StringMatcher und QByteArrayMatcher. Die Matcher haben auch statische Versionen, die zur Kompilierzeit erstellt werden, QStaticLatin1StringMatcher und QStaticByteArrayMatcher.
Weiterhin erwähnenswert:
- QStringLiteral ist ein Makro, das mit
u"foo"_s
identisch und ohne StringLiterals Namespace verfügbar ist. Vorzugsweise sollten Sie das moderne String-Literal verwenden. - QLatin1String ist ein Synonym für QLatin1StringView und existiert aus Gründen der Abwärtskompatibilität. Es ist keine eigene Zeichenkette und könnte in zukünftigen Versionen entfernt werden.
- QAnyStringView bietet eine Ansicht für eine Zeichenkette mit einer der drei unterstützten Kodierungen. Die Kodierung wird zusammen mit dem Verweis auf die Daten gespeichert. Diese Klasse ist gut geeignet, um Schnittstellen zu erstellen, die ein breites Spektrum von Stringtypen und Kodierungen annehmen. Im Gegensatz zu anderen Klassen wird keine Verarbeitung direkt auf QAnyStringView durchgeführt. Die Verarbeitung erfolgt auf der zugrunde liegenden QLatin1StringView, QUtf8StringView oder QStringView in der jeweiligen Kodierung. Verwenden Sie QAnyStringView::visit(), um dasselbe in Ihren eigenen Funktionen zu tun, die diese Klasse als Argument nehmen.
- Eine QLatin1StringView mit Nicht-ASCII-Zeichen ist in einer UTF-8-kodierten Quellcodedatei nicht einfach zu konstruieren und erfordert eine besondere Behandlung, siehe die Dokumentation QLatin1StringView.
- QStringRef ist ein Verweis auf einen Teil von QString, der im Qt5Compat-Modul aus Gründen der Abwärtskompatibilität verfügbar ist. Er sollte durch QStringView ersetzt werden.
String-bezogene Klassen auf hoher Ebene
Weitere High-Level-Klassen, die zusätzliche Funktionalität bieten, arbeiten hauptsächlich mit QString und somit mit UTF-16. Diese sind:
- QRegularExpression QRegularExpressionMatch und , um mit Mustervergleichen und regulären Ausdrücken zu arbeiten. QRegularExpressionMatchIterator
- QLocale zur Konvertierung von Zahlen und Daten in und aus Strings in einer Weise, die der Sprache und Kultur des Benutzers entspricht.
- QCollator und QCollatorSortKey, um Zeichenketten in Bezug auf die Sprache, das Skript oder das Gebiet des Benutzers zu vergleichen.
- QTextBoundaryFinder um satzfertigen Text gemäß den Unicode-Regeln aufzulösen.
QStringBuilder
eine interne Klasse, die die Leistung von String-Verkettungen mit dem Operator+
erheblich verbessert, siehe die Dokumentation QString.
Einige Klassen sind Vorlagen oder haben eine flexible API und arbeiten mit verschiedenen String-Klassen. Diese sind
- QTextStream zum Streamen in QIODevice, QByteArray oder QString
- QStringTokenizer zum Aufteilen von Strings
Welche String-Klasse soll verwendet werden?
Die allgemeine Anleitung zur Verwendung von String-Klassen lautet:
- Vermeiden Sie Kopieren und Speicherzuweisungen,
- Vermeiden Sie Kodierungsumwandlungen, und
- Wählen Sie die kompakteste Kodierung.
Qt bietet viele Funktionalitäten, um Speicherzuweisungen zu vermeiden. Die meisten Qt-Container verwenden Implicit Sharing für ihre Daten. Damit das implizite Sharing funktioniert, muss es eine ununterbrochene Kette derselben Klasse geben - eine Konvertierung von QString nach QStringView und zurück führt zu zwei QStrings, die ihre Daten nicht teilen. Daher müssen Funktionen ihre Daten als QString übergeben (sowohl Werte als auch Referenzen funktionieren). Das Extrahieren von Teilen einer Zeichenkette ist bei impliziter Datenfreigabe nicht möglich. Um Teile einer längeren Zeichenkette zu verwenden, verwenden Sie String Views, eine explizite Form der gemeinsamen Datennutzung.
Konvertierungen zwischen Kodierungen können durch die Beibehaltung einer bestimmten Kodierung reduziert werden. Daten, die z. B. in UTF-8 empfangen werden, werden am besten in UTF-8 gespeichert und verarbeitet, wenn keine Konvertierung in eine andere Kodierung erforderlich ist. Vergleiche zwischen Zeichenketten der gleichen Kodierung sind am schnellsten, und das Gleiche gilt für die meisten anderen Operationen. Wenn Strings einer bestimmten Kodierung häufig verglichen oder in eine andere Kodierung konvertiert werden, kann es von Vorteil sein, sie einmal zu konvertieren und zu speichern. Einige Operationen bieten viele Überladungen (oder eine QAnyStringView Überladung), um verschiedene Stringtypen und Kodierungen zu verarbeiten, und sie sollten die zweite Wahl sein, um die Leistung zu optimieren, wenn die Verwendung der gleichen Kodierung nicht möglich ist. Explizite Kodierungsumwandlungen vor dem Aufruf einer Funktion sollten nur als letzter Ausweg in Frage kommen, wenn keine andere Option verfügbar ist. Latin-1 ist eine sehr einfache Kodierung, und Operationen zwischen Latin-1 und jeder anderen Kodierung sind fast so effizient wie Operationen zwischen derselben Kodierung.
Die effizienteste Kodierung (von der effizientesten bis zur am wenigsten effizienten Latin-1, UTF-8, UTF-16) sollte gewählt werden, wenn keine anderen Beschränkungen die Kodierung bestimmen. Für Fehlerbehandlung und Protokollierung ist QLatin1StringView normalerweise ausreichend. Für den Benutzer sichtbare Strings in Qt sind immer vom Typ QString und als solche UTF-16 kodiert. Daher ist es am effektivsten, QStrings, QStringViews und QStringLiterals während der gesamten Lebenszeit eines für den Benutzer sichtbaren Strings zu verwenden. Die Funktion QObject::tr() liefert die richtige Kodierung und den richtigen Typ. QByteArray sollte verwendet werden, wenn die Kodierung keine Rolle spielt, z.B. um binäre Daten zu speichern, oder wenn die Kodierung unbekannt ist.
String-Klasse zur Erstellung von API
Mitgliedsvariablen
Mitgliedsvariablen sollten in fast allen Fällen von einem eigenen Typ sein. Views können nur dann als Membervariablen verwendet werden, wenn die Lebensdauer des referenzierten Owning Strings garantiert die Lebensdauer des Objekts überschreitet.
Funktionsargumente
Funktionsargumente sollten in den meisten Fällen String-Views einer geeigneten Kodierung sein. QAnyStringView kann als Parameter verwendet werden, um mehr als eine Kodierung zu unterstützen, und QAnyStringView::visit() kann intern verwendet werden, um sich in Funktionen für einzelne Kodierungen zu verzweigen. Wenn die Funktion auf eine einzige Kodierung beschränkt ist, sollte QLatin1StringView, QUtf8StringView, QStringView oder QByteArrayView verwendet werden.
Wenn die Funktion das Argument in einem eigenen String speichert (normalerweise eine Setter-Funktion), ist es am effizientesten, denselben String als Funktionsargument zu verwenden, um die implizite Data-Sharing-Funktionalität von Qt zu nutzen. Die besitzende Zeichenkette kann als const
Referenz übergeben werden. Das Überladen von Funktionen mit mehreren besitzenden und nicht besitzenden Stringtypen kann zu Überladungsmehrdeutigkeit führen und sollte vermieden werden. Eigene Stringtypen in Qt können automatisch in ihre nicht-eigene Version oder in QAnyStringView konvertiert werden.
Rückgabewerte
Temporäre Strings müssen als eigener String zurückgegeben werden, normalerweise QString. Wenn die zurückgegebene Zeichenkette zur Kompilierzeit bekannt ist, verwenden Sie u"foo"_s
, um die QString Struktur zur Kompilierzeit zu konstruieren. Wenn vorhandene eigene Zeichenketten (z. B. QString) von einer Funktion vollständig zurückgegeben werden (z. B. einer Getter-Funktion), ist es am effizientesten, sie als Referenz zurückzugeben. Sie können auch als Wert zurückgegeben werden, um in der Zukunft eine temporäre Rückgabe zu ermöglichen. Qt's Verwendung von implizitem Sharing vermeidet die Leistungseinflüsse von Allokation und Kopieren bei der Rückgabe über einen Wert.
Teile von existierenden Strings können effizient mit einer String-Ansicht der entsprechenden Kodierung zurückgegeben werden. Ein Beispiel dafür ist QRegularExpressionMatch::capturedView(), das eine QStringView zurückgibt.
String-Klasse für die Nutzung der API
Um eine Qt-API effizient nutzen zu können, sollten Sie versuchen, die Argumenttypen der Funktionen anzupassen. Wenn Sie in Ihrer Wahl eingeschränkt sind, wird Qt verschiedene Konvertierungen durchführen: Eigene Strings werden implizit in nicht-eigene Strings umgewandelt, nicht-eigene Strings können ihre eigenen Gegenstücke erzeugen, siehe zum Beispiel QStringView::toString(). Kodierungskonvertierungen werden in vielen Fällen implizit durchgeführt, dies sollte aber nach Möglichkeit vermieden werden. Um eine versehentliche implizite Konvertierung von UTF-8 zu vermeiden, können Sie das Makro QT_NO_CAST_FROM_ASCII aktivieren.
Wenn Sie eine Zeichenkette zur Laufzeit zusammensetzen müssen, bevor Sie sie an eine Funktion übergeben, benötigen Sie eine eigene Zeichenkette und damit QString. Wenn das Funktionsargument QStringView oder QAnyStringView ist, wird es implizit konvertiert.
Wenn die Zeichenkette zur Kompilierzeit bekannt ist, gibt es Raum für Optimierungen. Wenn die Funktion eine QString akzeptiert, sollten Sie sie mit u"foo"_s
oder dem Makro QStringLiteral erstellen. Wenn die Funktion eine QStringView erwartet, wird sie am besten mit einem gewöhnlichen UTF-16-Stringliteral u"foo"
erstellt, wenn eine QLatin1StringView erwartet wird, erstellen Sie sie mit "foo"_L1
. Wenn Sie die Wahl zwischen beiden haben, zum Beispiel wenn die Funktion QAnyStringView erwartet, verwenden Sie die engste Kodierung, normalerweise Latin-1.
Liste aller stringbezogenen Klassen
Einheitliche Sicht auf Latin-1, UTF-8 oder UTF-16 Strings mit einer schreibgeschützten Teilmenge der QString API | |
Array von Bytes | |
Liste von Byte-Arrays | |
Enthält eine Folge von Bytes, die schnell in einem Byte-Array abgeglichen werden können | |
Ansicht auf ein Array von Bytes mit einer schreibgeschützten Teilmenge der QByteArray API | |
16-Bit-Unicode-Zeichen | |
Vergleicht Strings nach einem lokalisierten Sortieralgorithmus | |
Kann verwendet werden, um die Kollationierung von Strings zu beschleunigen | |
8-Bit ASCII/Latin-1-Zeichen | |
Optimierte Suche nach Teilstrings in Latin-1-Text | |
Dünner Wrapper um ein US-ASCII/Latin-1 kodiertes String-Literal | |
Konvertierung zwischen Zahlen und ihren String-Repräsentationen in verschiedenen Sprachen | |
Mustervergleich mit regulären Ausdrücken | |
Die Ergebnisse eines Abgleichs eines QRegularExpression mit einer Zeichenkette | |
Iterator für die Ergebnisse einer globalen Übereinstimmung eines QRegularExpression-Objekts mit einer Zeichenkette | |
Kompilierzeit-Version von QByteArrayMatcher | |
Kompilierzeit-Version von QLatin1StringMatcher | |
Unicode-Zeichenkette | |
Basisklasse für die Kodierung und Dekodierung von Text | |
Zustandsbasierter Decoder für Text | |
Zustandsbasierter Kodierer für Text | |
Liste von Zeichenketten | |
Enthält eine Folge von Zeichen, die schnell in eine Unicode-Zeichenkette eingefügt werden können | |
Dünner Wrapper um QString-Substrings | |
Zerlegt Strings in Token entlang vorgegebener Trennzeichen | |
Einheitliche Sicht auf UTF-16-Strings mit einer schreibgeschützten Teilmenge der QString-API | |
Möglichkeit, Unicode-Textgrenzen in einer Zeichenkette zu finden | |
Bequeme Schnittstelle zum Lesen und Schreiben von Text | |
Einheitliche Sicht auf UTF-8-Strings mit einer schreibgeschützten Teilmenge der QString-API |
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.