STL- oder Qt-Container?

185

Was sind die Vor- und Nachteile der Qt - Container mit ( QMap, QVectorusw.) über ihre STL gleichwertig?

Ich sehe einen Grund, Qt zu bevorzugen:

  • Qt-Container können an andere Teile von Qt weitergegeben werden. Zum Beispiel können sie verwendet werden, um a QVariantund dann a zu füllen QSettings(mit einigen Einschränkungen werden jedoch nur QListund QMap/ QHashderen Schlüssel Zeichenfolgen akzeptiert werden).

Gibt es noch andere?

Bearbeiten : Angenommen, die Anwendung basiert bereits auf Qt.

Julien-L
quelle

Antworten:

135

Ich habe angefangen, std::(w)stringausschließlich die STL-Container zu verwenden und in / aus den Qt-Äquivalenten zu konvertieren, aber ich habe bereits zu gewechselt QStringund stelle fest, dass ich immer mehr Qt-Container verwende.

Wenn es um Strings geht, QStringbietet es eine viel umfassendere Funktionalität als std::basic_stringUnicode und ist vollständig Unicode-fähig. Es bietet auch eine effiziente COW-Implementierung , auf die ich mich stark verlassen habe.

Qts Container:

  • bieten die gleiche COW-Implementierung wie in QString, was äußerst nützlich ist, wenn das Qt- foreachMakro (das eine Kopie erstellt) und Metatypen oder Signale und Slots verwendet werden.
  • kann Iteratoren im STL-Stil oder Iteratoren im Java-Stil verwenden
  • sind streambar mit QDataStream
  • werden häufig in der Qt-API verwendet
  • haben eine stabile Implementierung über Betriebssysteme hinweg. Eine STL-Implementierung muss dem C ++ - Standard entsprechen, kann aber ansonsten frei tun, was sie will (siehe die std::stringCOW-Kontroverse). Einige STL-Implementierungen sind besonders schlecht.
  • Stellen Sie Hashes bereit, die nur verfügbar sind, wenn Sie TR1 verwenden

Die QTL hat eine andere Philosophie als die STL, die von J. Blanchette gut zusammengefasst wird: "Während die Container von STL für die Rohgeschwindigkeit optimiert sind, wurden die Containerklassen von Qt sorgfältig entwickelt, um Komfort, minimalen Speicherbedarf und minimale Codeerweiterung zu bieten."
Der obige Link enthält weitere Details zur Implementierung der QTL und zu den verwendeten Optimierungen.

Rollenspiel
quelle
12
Im neuen Standard c ++ 0x ist COW so ziemlich vom Tisch.
16
Betreff: "sorgfältig entwickelt, um [...] minimale Speichernutzung zu gewährleisten". Sie sollten Marketing nicht glauben. Profil QList<double>auf einer 32-Bit-Architektur zur Speichernutzung, um sich selbst davon zu überzeugen.
Marc Mutz - mmutz
11
"Es bietet auch eine effiziente COW-Implementierung": COW ist nicht besonders effizient, wenn es um Multithread-Anwendungen geht ...
Grizzly
5
@ MarcMutz-mmutz versucht zum Profil QVectorstatt QList. Es gibt ziemlich viele Qt-Erklärungen, dass QList zum Speichern von Zeigern auf Objekte entwickelt wurde. So wird jedes dynamisch erstellte Doppelelement und der Zeiger auf dieses Element gespeichert QList. QList ist als "mittlerer" Container zwischen Vektor und verknüpfter Liste konzipiert. Es ist nicht für speicher- / leistungskritische Fälle konzipiert.
Dmitry Sazonov
2
@ user1095108 Daran ist nichts auszusetzen. Geh und benutze die stl. Einige von uns bevorzugen es, schnell den richtigen Code zu schreiben. Daran ist auch nichts auszusetzen.
weberc2
178

Diese Frage ist schwer zu beantworten. Es kann wirklich auf ein philosophisches / subjektives Argument hinauslaufen.

Davon abgesehen ...

Ich empfehle die Regel "Wenn in Rom ... mach wie die Römer"

Das heißt, wenn Sie sich im Qt-Land befinden, codieren Sie wie die Qt'ianer. Dies gilt nicht nur aus Gründen der Lesbarkeit / Konsistenz. Überlegen Sie, was passiert, wenn Sie alles in einem stl-Container speichern, dann müssen Sie all diese Daten an eine Qt-Funktion übergeben. Möchten Sie wirklich eine Menge Code verwalten, der Dinge in / aus Qt-Containern kopiert? Ihr Code ist bereits stark von Qt abhängig, daher ist es nicht so, als würden Sie ihn durch die Verwendung von stl-Containern "standardisierter" machen. Und wozu dient ein Container, wenn Sie ihn jedes Mal, wenn Sie ihn für nützliche Zwecke verwenden möchten, in den entsprechenden Qt-Container kopieren müssen?

Doug T.
quelle
1
+1 Sie haben vollkommen recht, das habe ich in meiner Frage zu erklären versucht ("Ich sehe einen Grund, Qt zu bevorzugen"), also habe ich es leicht bearbeitet. Vielen Dank
Julien-L
Absolut gut gesagt. Wenn Sie QT machen, verwenden Sie das QT-Zeug! Stellen Sie sich den "WTF" -Moment für den Betreuer vor, wenn er eine QT-Anwendung öffnet und sieht, dass QT und STL austauschbar verwendet werden. Das könnte ein (unnötiger) Albtraum werden.
Pete
5
@ It'sPete STL ist Teil des Standards; QT ist nicht. Jeder Code, der den Standard verwendet, sollte niemals einen "WTF" -Moment auslösen.
Alice
5
Die Römer legten ihre Gefangenen in das Kolosseum und jagten sie dann mit Löwen. Wenn Sie es besser wissen, folgen Sie nicht den lokalen Gewohnheiten. Das ist in Qt genauso wahr wie für Modern Man im Römischen Reich ...
Marc Mutz - mmutz
1
@mmutz du sagst, dass es eine schlechte Sache ist, ich möchte einen Code, den ich in diesem Kolosseum gefunden habe, einfügen und die Show sehen
slf
64

Die Qt-Container sind begrenzter als die STL-Container. Einige Beispiele dafür, wo die STL überlegen sind (all dies habe ich in der Vergangenheit getroffen):

  • STL ist standardisiert, ändert sich nicht mit jeder Qt-Version (Qt 2 hatte QList(zeigerbasiert) und QValueList(wertebasiert); Qt 3 hatte QPtrListund QValueList; Qt 4 hat jetzt QListund es ist überhaupt nichts wie QPtrList oder QValueList ).
    Selbst wenn Sie am Ende die Qt-Container verwenden, verwenden Sie die STL-kompatible API-Teilmenge (dh push_back()nicht append(); front(), nicht first(), ...), um eine erneute Portierung zu vermeiden. Kommen Sie zu Qt 5. Sowohl in Qt2-> 3 als auch in Qt3-> 4 Übergänge, die Änderungen in den Qt-Containern gehörten zu denen, die die meiste Code-Abwanderung erforderten.
  • Bidirektionale STL-Container haben alle rbegin()/ rend(), wodurch die umgekehrte Iteration symmetrisch zur Vorwärtsiteration ist. Nicht alle Qt-Container haben sie (die assoziativen nicht), daher ist die umgekehrte Iteration unnötig kompliziert.
  • STL-Container reichen insert()von verschiedenen, aber kompatiblen Iteratortypen, sodass sie std::copy()viel seltener benötigt werden.
  • STL-Container verfügen über ein AllocatorVorlagenargument, wodurch die benutzerdefinierte Speicherverwaltung im Vergleich zu Qt (Fork of erforderlich für ) trivial ist (typedef erforderlich ). EDIT 20171220 : Dies reduziert Qt von Fortschritten im Allokator-Design nach C ++ 11 und C ++ 17, vgl. zB John Lakos 'Vortrag ( Teil 2 ).QLineEdits/QString/secqstring/
  • Es gibt kein Qt-Äquivalent zu std::deque.
  • std::listhat splice(). Wann immer ich mich benutze std::list, liegt es daran, dass ich es brauche splice().
  • std::stack, std::queueAggregieren ihre zugrunde liegenden Behälter richtig, und nicht erben sie, wie QStack, QQueuetun.
  • QSetist wie std::unordered_set, nicht wie std::set.
  • QListist einfach komisch .

Viele der oben genannten Probleme könnten in Qt recht einfach gelöst werden , aber die Containerbibliothek in Qt scheint derzeit einen Mangel an Entwicklungsfokus zu haben.

EDIT 20150106 : Nachdem ich einige Zeit damit verbracht habe, C ++ 11-Unterstützung für Qt 5-Containerklassen bereitzustellen, habe ich entschieden, dass sich die Arbeit nicht lohnt. Wenn Sie sich die Arbeit ansehen, die in C ++ - Standardbibliotheksimplementierungen integriert wird, ist klar, dass die Qt-Klassen niemals aufholen werden. Wir haben Qt 5.4 jetzt freigegeben undQVector noch nicht Elemente auf Umschichtungen nicht bewegt, muss nichtemplace_back()oder rvalue-push_back()... Wir lehnten kürzlich auch eineQOptionalKlassenvorlage und wartet daraufstd::optionalstatt. Ebenso fürstd::unique_ptr. Ich hoffe, dass sich dieser Trend fortsetzt.

Marc Mutz - mmutz
quelle
3
Huh. Ich hatte den Eindruck , QList war das Äquivalent zu std::deque. Natürlich hätte ich die Dokumentation nicht einfach überfliegen sollen.
Dennis Zickefoose
QVectorhat crbeginund Freunde seit Qt 5.6
Bart Louwers
@Alex: Richtig, ich habe die einfachen hinzugefügt, aber noch nicht alle Qt-Container haben sie (weil Sie nicht std::reverse_iteratorüber die kaputten verwendenQHash / QMapIteratoren, die, wenn sie dereferenziert, Rückkehr mapped_typestatt value_type). Nichts, was nicht behoben werden kann, aber siehe meine EDIT von 2015.
Marc Mutz - mmutz
@ MarcMutz-mmutz Danke für die Klarstellung.
Bart Louwers
Kann sich lohnen , die Tatsache zu der Liste hinzugefügt werden , dass zB QVectorVerwendungen intals sein Index, so dass 31-Bit - Größen (auch auf 64-Bit - Systeme) zu begrenzen. Darüber hinaus können nicht einmal INT_MAXElemente mit einer Größe von mehr als 1 Byte gespeichert werden. Zum Beispiel war das größte, das .size()ich QVector<float>unter x86_64 Linux gcc haben konnte, 536870907 Elemente (2²⁹-5), während std::vector<float>erfolgreich 4294967295 Elemente (2³²-1 ) zugewiesen wurden. ).
Ruslan
31

Zerlegen wir diese Behauptungen in tatsächlich messbare Phänomene:

  • Leichter: Qt-Container verbrauchen weniger Speicher als STL-Container
  • Sicherer: Qt-Behälter haben weniger Gelegenheit, unsachgemäß verwendet zu werden
  • Einfacher: Qt-Container stellen eine geringere intellektuelle Belastung dar

Einfacher

In diesem Zusammenhang wird behauptet, dass die Iteration im Java-Stil irgendwie "einfacher" als der STL-Stil ist und daher Qt aufgrund dieser zusätzlichen Schnittstelle einfacher zu verwenden ist.

Java-Stil:

QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

STL-Stil:

QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

Der Java-Iterator-Stil hat den Vorteil, dass er etwas kleiner und sauberer ist. Das Problem ist, dass dies nicht mehr der STL-Stil ist.

C ++ 11 STL-Stil

for( auto i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

oder

C ++ 11 für jeden Stil

for (QString i : list)
    qDebug << i;

Das ist so drastisch einfach, dass es keinen Grund gibt, jemals etwas anderes zu verwenden (es sei denn, Sie unterstützen C ++ 11 nicht).

Mein Favorit ist jedoch:

BOOST_FOREACH(QString i, list)
{
    qDebug << i;
}

Wie wir sehen können, bringt uns diese Schnittstelle nichts weiter als eine zusätzliche Schnittstelle, zusätzlich zu einer bereits schlanken, optimierten und modernen Benutzeroberfläche. Hinzufügen einer unnötigen Abstraktionsebene über eine bereits stabile und verwendbare Schnittstelle? Nicht meine Vorstellung von "einfacher".

Qt foreach- und Java-Schnittstellen erhöhen den Overhead. Sie kopieren die Struktur und bieten eine unnötige Indirektionsebene. Dies scheint nicht viel zu sein, aber warum sollte eine zusätzliche Overhead-Schicht hinzugefügt werden, um eine nicht allzu viel einfachere Benutzeroberfläche bereitzustellen? Java verfügt über diese Schnittstelle, da Java keine Operatorüberladung aufweist. C ++ tut es.

Sicherer

Die Rechtfertigung, die Qt gibt, ist das implizite Austauschproblem, das weder implizit noch ein Problem ist. Es beinhaltet jedoch das Teilen.

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/

Erstens ist dies nicht implizit; Sie weisen explizit einen Vektor einem anderen zu. Die STL-Iteratorspezifikation zeigt deutlich an, dass Iteratoren zum Container gehören. Daher haben wir eindeutig einen gemeinsam genutzten Container zwischen b und a eingeführt. Zweitens ist dies kein Problem. Solange alle Regeln der Iteratorspezifikation eingehalten werden, wird absolut nichts schief gehen. Das einzige Mal, wenn etwas schief geht, ist hier:

b.clear(); // Now the iterator i is completely invalid.

Qt gibt dies so an, als ob es etwas bedeutet, so wie ein Problem de novo aus diesem Szenario entsteht. Das tut es nicht. Der Iterator ist ungültig und funktioniert genau wie alles, auf das von mehreren nicht zusammenhängenden Bereichen aus zugegriffen werden kann. Tatsächlich wird dies bei Iteratoren im Java-Stil in Qt leicht auftreten, da es stark auf implizites Teilen angewiesen ist, das ein Antimuster ist, wie hier dokumentiert , und in vielen anderen Bereichen . Es scheint besonders seltsam, diese "Optimierung" in einem Framework einzusetzen, das sich immer mehr in Richtung Multithreading bewegt, aber das ist Marketing für Sie.

Feuerzeug

Dieser ist etwas kniffliger. Die Verwendung von Copy-On-Write- und impliziten Sharing- und Wachstumsstrategien macht es sehr schwierig, tatsächlich Garantien dafür zu geben, wie viel Speicher Ihr Container zu einem bestimmten Zeitpunkt verbraucht. Dies ist anders als bei der STL, die Ihnen starke algorithmische Garantien bietet.

Wir wissen, dass die minimale Grenze des verschwendeten Raums für einen Vektor die Quadratwurzel der Länge des Vektors ist , aber es scheint keine Möglichkeit zu geben, dies in Qt zu implementieren. Die verschiedenen "Optimierungen", die sie unterstützen, würden diese sehr wichtige platzsparende Funktion ausschließen. Die STL benötigt diese Funktion nicht (und die meisten verwenden ein doppeltes Wachstum, was verschwenderischer ist), aber es ist wichtig zu beachten, dass Sie diese Funktion bei Bedarf zumindest implementieren können.

Gleiches gilt für doppelt verknüpfte Listen, bei denen die XOr-Verknüpfung verwendet werden könnte, um den verwendeten Speicherplatz drastisch zu reduzieren. Auch dies ist bei Qt aufgrund der Anforderungen an Wachstum und COW nicht möglich.

COW kann in der Tat etwas leichter machen, aber auch aufdringliche Container, wie sie durch Boost unterstützt werden , und Qt haben diese in früheren Versionen häufig verwendet, aber sie werden nicht mehr so ​​oft verwendet, weil sie schwer zu verwenden, unsicher und belastend sind auf dem Programmierer. COW ist eine viel weniger aufdringliche Lösung, aber aus den oben genannten Gründen unattraktiv.

Es gibt keinen Grund, warum Sie keine STL-Container mit denselben oder geringeren Speicherkosten als die Container von Qt verwenden könnten, mit dem zusätzlichen Vorteil, dass Sie tatsächlich wissen, wie viel Speicher Sie zu einem bestimmten Zeitpunkt verschwenden werden. Es ist leider unmöglich, die beiden in Bezug auf die Rohspeichernutzung zu vergleichen, da solche Benchmarks in verschiedenen Anwendungsfällen sehr unterschiedliche Ergebnisse zeigen würden, was genau die Art von Problem ist, für deren Behebung die STL entwickelt wurde.

Abschließend

Vermeiden Sie die Verwendung von Qt-Containern, wann immer dies möglich ist, ohne dass Kopierkosten anfallen, und verwenden Sie nach Möglichkeit eine Iteration vom Typ STL (möglicherweise über einen Wrapper oder die neue Syntax).

Alice
quelle
4
Ihre Punkte sind weitgehend gültig, aber es gibt einige irreführende Informationen: Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".Qts Iteratoren im Java-Stil wurden nicht zu C ++ 11 hinzugefügt; sie sind älter als sie. Auf foreach(QString elem, list)jeden Fall ist Qt's genauso einfach wie Ceachs foreach oder BOOST_FOREACH und funktioniert mit Compilern, die vor C ++ 11 kompatibel sind.
weberc2
@ weberc2 Du bist verwirrt; Die Java-Iteratoren von Qt werden zusätzlich zu den C ++ - Iteratoren (nicht C ++ 11) hinzugefügt. Es ist eine zusätzliche Abstraktionsebene (und eine unnötige), die die Benutzeroberfläche aufbläht, was nicht einfacher ist. Und foreach für Qt ist nicht so einfach wie BOOST_FOREACH, da es insbesondere nicht so sicher ist und nicht die gleiche Breite an Unterstützung bietet (BOOST_FOREACH kann für jeden Bereich für jede Version von C ++ gelten, wobei foreach in QT C + erfordert +03 Compliance). QTs foreach sollte unter allen Umständen vermieden werden.
Alice
So, as we can see, this interface gains us nothing except an additional interface, *on top of* an already sleek, streamlined, and modern interface. Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".(Hervorhebung von mir) Sie haben dies direkt gesagt, nachdem Sie uns C ++ 11- und BOOST-Versionen von foreach gezeigt haben, sodass es so klingt, als ob die Qt-Version aus einer dieser beiden Versionen aufgebaut ist, was AFAICT nicht der Fall ist. Ich bin sicher, das haben Sie nicht gemeint, aber so kommt es zustande. Daher "irreführende Informationen".
weberc2
It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier.Es ist immer noch unklar, womit Sie vergleichen. C ++ 03 Iteratoren? C ++ 11 Iteratoren? BOOST_FOREACH? Alles das oben Genannte?
weberc2
1
Ich sage nur, Sie sind oft sehr zweideutig, auf welche Iterationsmethode Sie sich beziehen. Ich glaube, Sie denken, Sie sind klar und Ihre Sprache ist vernünftig, aber es scheint seltsam, sich zu weigern, etwas zu spezifizieren. Stimmen Sie zu, nicht zuzustimmen, nehme ich an.
weberc2
22

STL-Container:

  • Leistungsgarantien haben
  • Kann in STL-Algorithmen verwendet werden, die auch Leistungsgarantien haben
  • Kann von C ++ - Bibliotheken von Drittanbietern wie Boost genutzt werden
  • Sind Standard und überleben wahrscheinlich proprietäre Lösungen
  • Förderung der generischen Programmierung von Algorithmen und Datenstrukturen. Wenn Sie neue Algorithmen und Datenstrukturen schreiben, die STL-konform sind, können Sie das, was STL bereits bietet, kostenlos nutzen.
fbrereto
quelle
5
Alle oben genannten Punkte, außer dass sie ein Standard sind, gelten auch für die QTL, vorausgesetzt, Sie kompilieren Qt mit STL-Unterstützung (Standardeinstellung). Die STL-Unterstützung umfasst Iteratorfunktionen, Containertypedefs (const_iterator usw.) und Konvertierungsfunktionen (von / nach STL).
RPG
2
Qt ist nicht proprietär
txwikinger
2
@rpg Fast alle von ihnen gelten nicht für QTL; QTL hat keine starken Leistungsgarantien (da sie diese in der Vergangenheit leicht gebrochen haben), sind nicht STL-konform (kein Reverse und können daher nicht mit viel Boost verwendet werden), sind nicht Standard (sie ändern sich ständig zwischen den Versionen) und tun dies generische Programmierung nicht fördern (sie haben zum Beispiel keine Vorlagenargumente für Allokatoren).
Alice
15

Qt-Container verwenden die Copy-on-Write-Sprache.

TimW
quelle
2
+1, könnte ein bedeutender Vorteil in
Bezug
31
Oder könnte ein erheblicher Nachteil sein. Siehe gotw.ca/publications/optimizations.htm
Kaz Dragon
3
Der Atom-Refcount scheint ziemlich gut abzuschneiden
rpg
STL-Container können alle vorhandenen Redewendungen verwenden, sofern sie ihre Leistungsgarantien und die Spezifikationen erfüllen. COW ist auch unter C ++ 11 / C ++ 14 STL gültig.
Alice
1
@Alice COW ist die meiste Zeit keine gültige Implementierung, da sie in fast jedem Fall die Komplexität des Standards verletzt und die Gültigkeit des Iterators garantiert. Eine der wenigen Klassen, die mit COW implementiert werden konnten, war, std::basic_stringund der Standard hat mit C ++ 11 Maßnahmen ergriffen, um diese nicht konform zu machen.
Tiago Gomes
9

Eines der Hauptprobleme ist, dass die API von Qt erwartet, dass Sie Daten in den Containern von Qt bereitstellen. Sie können also auch einfach die Qt-Container verwenden, anstatt zwischen den beiden hin und her zu wechseln.

Wenn Sie die Qt-Container bereits verwenden, ist es möglicherweise etwas optimaler, sie ausschließlich zu verwenden, da Sie die STL-Header-Dateien nicht einschließen und möglicherweise in die STL-Bibliotheken verlinken müssten. Abhängig von Ihrer Toolchain kann dies jedoch trotzdem passieren. Rein aus gestalterischer Sicht ist Konsistenz im Allgemeinen eine gute Sache.

qid
quelle
1
Die Rate, mit der Sie in einer realen Anwendung, die STL verwendet, zwischen STL- und Qt-Containern "hin und her transformieren" müssen, es sei denn, die Schnittstelle zu Qt wird im Allgemeinen stark überschätzt. Meistens führen Sie eine std :: transform durch, die zur / von der Präsentationsebene kommt (die Qt verwendet), und Sie erhalten den Container-Switch kostenlos. Interessenten können unter projects.kde.org/projects/kde/kdepim/repository/revisions/… nachsehen , um sich selbst davon zu überzeugen.
Marc Mutz - mmutz
8

Wenn die Daten, mit denen Sie arbeiten, hauptsächlich zur Steuerung der Qt-basierten Benutzeroberfläche verwendet werden, verwenden Sie auf jeden Fall Qt-Container.

Wenn die Daten meistens intern in der App verwendet werden und Sie wahrscheinlich nie von Qt weg portieren, verwenden Sie die Qt-Container, sofern keine Leistungsprobleme auftreten, da dadurch die Datenbits, die an die Benutzeroberfläche gelangen, einfacher zu verarbeiten sind.

Wenn die Daten hauptsächlich in Verbindung mit anderen Bibliotheken verwendet werden, die nur über STL-Container Bescheid wissen, verwenden Sie STL-Container. Wenn Sie diese Situation haben, sind Sie in Schwierigkeiten, egal was passiert, weil Sie viel zwischen Containertypen hin und her portieren werden, egal was Sie tun.

Michael Kohne
quelle
7

Neben dem COW-Unterschied werden STL-Container auf einer Vielzahl von Plattformen viel häufiger unterstützt. Qt ist portabel genug, wenn Sie Ihre Arbeit auf "Mainstream" -Plattformen beschränken, aber die STL ist auch auf vielen anderen undurchsichtigeren Plattformen verfügbar (z. B. DSPs von Texas Instruments).

Da die STL eher Standard ist als von einem einzelnen Unternehmen kontrolliert wird, gibt es im Allgemeinen mehr Programmierer, die STL-Code leicht lesen, verstehen und ändern können, und mehr Ressourcen (Bücher, Online-Foren, Konferenzen usw.), um sie zu unterstützen tun dies als es für Qt gibt. Das heißt nicht, dass man Qt allein aus diesem Grund scheuen sollte; Wenn alle anderen Dinge gleich sind, sollten Sie standardmäßig die STL verwenden, aber natürlich sind alle Dinge selten gleich, sodass Sie in Ihrem eigenen Kontext entscheiden müssen, was am sinnvollsten ist.

In Bezug auf die Antwort von AlexKR: Die STL-Leistung ist in Grenzen garantiert, aber eine bestimmte Implementierung kann plattformabhängige Details verwenden, um ihre STL zu beschleunigen . In diesem Sinne können Sie auf verschiedenen Plattformen unterschiedliche Ergebnisse erzielen, diese sind jedoch niemals langsamer als die explizite Garantie (Modulo-Fehler).

Metall
quelle
9
In Bezug auf Ihren ersten Punkt: Ich gehe davon aus, dass sich das OP auf Projekte bezieht, die bereits Qt verwenden und daher bereits auf "Mainstream" -Plattformen beschränkt sind. Es ist unwahrscheinlich, dass jemand eine so schwergewichtige Bibliothek wie Qt nur für seine Containerklassen heranzieht.
ThisSuitIsBlackNot
4

Meine fünf Cent: Qt-Container sollen auf verschiedenen Plattformen ähnlich funktionieren. Während STL-Container von der STL-Implementierung abhängen. Möglicherweise erhalten Sie unterschiedliche Leistungsergebnisse.

EDIT: Ich sage nicht, dass STL "langsamer" ist, aber ich weise auf die Auswirkungen verschiedener Implementierungsdetails hin.
Bitte überprüfen Sie dies und dann vielleicht das .
Und es ist kein wirkliches Problem von STL. Wenn Sie einen signifikanten Leistungsunterschied haben, liegt offensichtlich ein Problem im Code vor, der STL verwendet.

alexkr
quelle
STL-Container sind unabhängig von der Implementierung alle ähnlich. Sie können einen Vektor nicht wie eine Liste hinter den Kulissen implementieren lassen, da er sich in einem zusammenhängenden Speicherblock befinden muss. Die STL wird normalerweise auch auf allen wichtigen Plattformen in großem Umfang optimiert.
Yacoby
1
Wenn Sie sich an die Versprechen der STL halten (anstatt davon auszugehen, wie sie implementiert ist), werden Sie nie Probleme haben, zwischen Plattformen mit STL zu wechseln. Gleiches gilt für Qt.
Michael Kohne
Dies ist das genaue Gegenteil von wahr. STL-Container funktionieren auf allen Plattformen immer gleich. Wenn nicht, sind sie nicht STL. QT ändert jedoch die Leistung drastisch von Version zu Version, sodass Sie auf einer Plattform mit QT4.0 anstelle von QT4.8 einige schwerwiegende Änderungen erhalten können.
Alice
Sie verwechseln zwei sehr unterschiedliche Arten der Leistung; algorithmische Leistung und praktische Rechenleistung. Alle STL-Implementierungen garantieren die gleiche algorithmische Leistung. Wenn Ihr Vektor log (n) Zeit benötigt, um ein Element zu indizieren, ist er kein STL-Vektor. Ihre Links verweisen auf die praktische Rechenleistung, die in dieser Diskussion bedeutungslos ist. QT ändert seine Algorithmen zwischen den Versionen, und dasselbe C ++ auf verschiedenen Plattformen erzielt unterschiedliche Leistung. Diese sind meiner Erfahrung nach weitaus formbarer als Unterschiede in der STL-Leistung.
Alice
3

Ich denke, es hängt davon ab, wie Sie Qt verwenden. Wenn Sie es überall in Ihrem Produkt verwenden, ist es wahrscheinlich sinnvoll, Qt-Behälter zu verwenden. Wenn Sie es nur zum Beispiel für den UI-Teil enthalten, ist es möglicherweise besser, C ++ - Standardcontainer zu verwenden.

Nemanja Trifunovic
quelle
3

Ich bin der Meinung, dass STL eine hervorragende Software ist. Wenn ich jedoch eine KDE- oder Qt-bezogene Programmierung durchführen möchte, ist Qt der richtige Weg. Es hängt auch vom verwendeten Compiler ab, mit GCC funktioniert STL ziemlich gut. Wenn Sie jedoch beispielsweise SUN Studio CC verwenden müssen, wird STL Ihnen höchstwahrscheinlich Kopfschmerzen bereiten, da der Compiler nicht die STL an sich ist. In diesem Fall, da der Compiler Ihren Kopf verletzt, verwenden Sie einfach Qt, um Ihnen die Mühe zu ersparen. Nur meine 2 Cent ...

Paulo Lopes
quelle
3

Es gibt eine (manchmal) große Einschränkung in QVector. Es können nur int Bytes Speicher zugewiesen werden (beachten Sie, dass das Limit in Bytes und nicht in der Anzahl der Elemente liegt). Dies bedeutet, dass der Versuch, zusammenhängende Speicherblöcke mit einem QVector von mehr als ~ 2 GB zuzuweisen, zu einem Absturz führt. Dies geschieht mit Qt 4 und 5. std :: vector hat keine solche Einschränkung.

fedemp
quelle
0

Der Hauptgrund für STL-Container ist für mich, wenn Sie einen benutzerdefinierten Allokator benötigen, um Speicher in sehr großen Containern wiederzuverwenden. Angenommen, Sie haben eine QMap, in der 1000000 Einträge (Schlüssel / Wert-Paare) gespeichert sind. In Qt bedeutet dies genau 1000000 Millionen Zuweisungen ( newAnrufe), egal was passiert . In STL können Sie jederzeit einen benutzerdefinierten Zuweiser erstellen, der intern den gesamten Speicher auf einmal zuweist, und ihn jedem Eintrag zuweisen, wenn die Karte gefüllt wird.

Mein Rat ist, STL-Container zu verwenden, wenn leistungskritische Algorithmen in die Geschäftslogik geschrieben werden, und sie dann wieder in Qt-Container zu konvertieren, wenn die Ergebnisse bereit sind, indem sie bei Bedarf von Ihren UI-Steuerelementen und Formularen angezeigt werden.

Darien Pardinas
quelle
Nicht versuchen , die QTL hier zu verteidigen, aber man konnte sich spezialisieren QMapNode<K,V>für Ihre K, VIhr eigenes zu schaffen operator new.
Marc Mutz - mmutz